You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

IDIEP-126
Author
Sponsor
Created 10.09.2024
Status
DRAFT


Motivation

When processing data, users want to have access to non-tabular (not stored in cache structures) data. Example of such data is application attributes - an associative array specified on an application side. Usage scenarios:

  1. To run certain logic that depends on the value of the attribute (for example, the application language [2], progress monitoring [4]).
  2. To audit changes in the database (for example, CacheInterceptor extracts the user from the attributes and saves it along with data).
  3. To optimize the transfer of parameters to processing functions (for example, multiple QuerySqlFunction use the same parameter and it is convenient to take it from the attributes, rather than transfer it separately to each function).

Another examples of non-tabular data that can be accessed are SecuritySubject, UserAttributes and current Transaction.

The requirements include:

  1. Attributes must be accessible from user defined functions (QuerySqlFunction, CacheInterceptor).
  2. Setting attributes via protocols: thin client, jdbc:thin.
  3. Attribute values ​​can change during the life of the connection (a connection from a connection pool can be sequentially used by different applications).

Ignite does not have a similar public API:

  1. ServiceCallContext helps solve similar problems, but has several limitations. The main one is that it is only available in calls via the IgniteService API and cannot be used for single operations or transactions.
  2. UserAttributes - allows to set user attributes, but the attribute values ​​are fixed for the entire lifetime of the connection.
  3. ClientListenerConnectionContext - it's available only on single node, which accepts connection from a client.

A similar context mechanism exists in Oracle [1] and it's widely used. 

Description

Accessing attributes

  1. ApplicationContext is an entrypoint for accessing all non-tabular data.
  2. Access requires static methods, because objects injection isn't possible for user functions (QuerySqlFunction are static, CacheInterceptor is a singleton for cache).


/** ApplicationContext interface. It's an entrypoint for all non-tabular information. */
public class ApplicationContext {
    /** @return Application attributes set for current thread. */
    public static @Nullable Map<String, String> getAttributes();
 }
 
/** Example, use it in QuerySqlFunction. */
public static class UserDefinedFunctions {
    /** @return Session ID, application attribute. */
    @QuerySqlFunction
    public static String sessionId() {
        Map<String, String> appAttrs = ApplicationContext.getAttributes();
 
        return appAttrs == null ? null : appAttr.get(SESSION_ID);
    }
}

Setting attributes

Ignite 

  1. Ignite doesn't have support an abstraction "session". It also doesn't restrict usage on Ignite instance from multiple threads by different applications. Also the same thread can be shared between multiple applications.
  2. The application attributes might be used in SQL, Cache API. The ApplicationContext should not depend on the used API.
  3. Then minimal unit of interaction between application and Ignite is a transaction. I suggest to attach the attributes to a transaction.


// Extends the interface with new public method.
public interface IgniteTransactions {
 	...

    /** @param appAttrs Application attributes. */
    public IgniteTransactions withApplicationAttributes(Map<String, String> appAttrs);
}

// Example of usage.
try (Ignite ign = Ignition.localIgnite()) {
     Map<String, String> appAttrs = F.asMap("SESSION_ID", "1234");
 
     try (Transaction tx = ign.transactions().withApplicationAttributes(appAttrs).txStart()) { 
        ...
    }
}

IgniteClient (Java)

  1. Client should mirror the logic of Ignite node.
  2. New feature is needed in the ClientBitmaskFeature protocol.


// Extends the interface with new public method.
public interface ClientTransactions {
	...

    /** @param appAttrs Application attributes. */
    public ClientTransactions withApplicationAttributes(Map<String, String> appAttrs);
}

// Example of usage.
try (IgniteClient cln = Ignition.startClient(clnCfg)) {
    Map<String, String> appAttrs = F.asMap("SESSION_ID", "1234");

    try (ClientTransaction tx = cln.transactions().withApplicationAttributes(appAttrs).txStart()) {
        ...
    }
}

JDBC

The standard jdbc protocol describes the methods Connection#setClientInfo, which allow changing the values ​​of client attributes during the life of the connection [3]. Implementation features:

  1. The list of attributes that can be set using #setClientInfo is arbitrary. The documentation recommends strictly limiting the set of attributes, but this is not necessary. For example, Oracle does not have such a limitation [5]. The setClientInfo array is completely translated into the getClientAttributes array.
  2. The parameters set in setClientInfo are passed along with each JdbcRequest (this requires a new feature in JdbcThinFeature).
  3. The client must reset the set values ​​itself.


// JDBC connection to Ignite server.
try (Connection conn = DriverManager.getConnection(URL)) {
    conn.setClientInfo("SESSION_ID", "1234");
 
    ...
}

Spreading context across cluster nodes

  1. Via the QueryStartRequest SQL message protocol (for jdbc, SQL transactions)
  2. Via the transaction protocol for handling inserts (CacheInterceptor), since inserts are not always performed on the request initiator node.

Risks and Assumptions

// Describe project risks, such as API or binary compatibility issues, major protocol changes, etc.

  1. It doesn't work for non-transactional ignite-node SQL but work for JDBC.

Discussion Links

// Links to discussions on the devlist, if applicable.

Reference Links

[1] https://docs.oracle.com/en/database/oracle/oracle-database/19/dbseg/using-application-contexts-to-retrieve-user-information.html#GUID-51C9D5FA-6787-4F05-82EF-A5968BEDC5A0

[2] https://stackoverflow.com/questions/71067911/use-oracles-dbms-session-set-context-in-entity-framework-core

[3] https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html#setClientInfo(java.lang.String,java.lang.String)

[4] https://torofimofu.blogspot.com/2014/05/oracle.html

[5] https://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#BABDAEEC

Tickets

// Links or report with relevant JIRA tickets.

  • No labels