Class ODatabasePoolManager

java.lang.Object
org.gcube.informationsystem.resourceregistry.environments.ODatabasePoolManager

public class ODatabasePoolManager extends Object
Centralized, static, thread-safe registry of OrientDB connection pools, uniquely indexed by connection username (e.g. WriterUser_<Context-UUID>, HWriterUser_<Context-UUID>).

Environment and HierarchicalEnvironment are increasingly instantiated transiently (a fresh object per resolution, not cached — see InstanceEnvironmentRegistry), so a pool owned by the Environment instance itself would be created anew, and never closed, on every single resolution of the same context. Since the connection username is a deterministic function of the context UUID (and permission mode / hierarchical flag), pools can instead be shared across every transient instance that resolves to the same identity, closing the gap this class exists to close.

Cross-instance invalidation: confirmed empirically (2026-07-17) that an OrientDB ODatabasePool caches the authenticated user's role/permission state for the lifetime of the pool — not just of a single acquired session. Even a brand-new pool.acquire() on an existing pool returns a session carrying the role state from whenever the pool was first authenticated; only closing and recreating the pool (a fresh physical connection) picks up a since-changed role grant. Since ODatabasePools are inherently JVM-local, invalidatePoolsForContext(UUID) broadcasts the invalidation to every other service instance in the deployment over the shared ClusterEventBus, as a ClusterEventType.POOL_INVALIDATION event. The bus owns the transport (Redis pub/sub as the fast path, an OrientDB Live Query as the dependency-free backstop) and the de-duplication; this class only states what happened and reacts to it. The local invalidation is idempotent anyway, so a repeated delivery is harmless.

Schema changes: a pool also keeps the schema it loaded when it was created, so a Type created, updated or deleted afterwards is unknown to its sessions (a vertex of a new Type is refused as "not a vertex class"). Every instance learns of a Type change from the ClusterEventType.SCHEMA_CHANGE event, which only advances a local counter; a pool that loaded the schema before the last change reloads it when it is next asked for, in getPool(String, String, String). The pool and the sessions already acquired from it stay open: the schema is shared by all of them.

Author:
Luca Frosini (ISTI - CNR)
  • Method Summary

    Modifier and Type
    Method
    Description
    static boolean
    Discards every pool of this instance if the given failure, or one of its causes, is a connection to the database lost (an OIOException): after a database restart every pooled session holds a dead connection, and without this each of them would fail one request before being replaced.
    static com.orientechnologies.orient.core.db.ODatabasePool
    getPool(String url, String username, String password)
    Returns the shared pool for the given username, creating it if it does not exist yet, with the current Type schema: a pool that loaded it before the last schema change reloads it first, and is recreated if it cannot.
    static void
    Closes and discards every pool currently registered on this instance, regardless of the context or permission mode it was created for.
    static void
    Closes and removes the pool registered for the given username, if present.
    static void
    Closes and removes every pool (reader/writer, hierarchical/non-hierarchical) associated with the given context UUID on every service instance in the deployment (via Redis pub/sub, see the class-level note on cross-instance invalidation) — not just this one.
    static com.orientechnologies.orient.core.db.ODatabasePool
    recreatePool(String url, String username, String password)
    Closes and discards the current pool for the given username (if any), then creates and registers a fresh one.
    static void
    Records that the Type schema changed, so that every pool of this instance reloads it before handing out its next session (see getPool(String, String, String)).

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • schemaChanged

      public static void schemaChanged()
      Records that the Type schema changed, so that every pool of this instance reloads it before handing out its next session (see getPool(String, String, String)). Performs no I/O: it is called from a ClusterEventBus consumer, which must not block.
    • getPool

      public static com.orientechnologies.orient.core.db.ODatabasePool getPool(String url, String username, String password)
      Returns the shared pool for the given username, creating it if it does not exist yet, with the current Type schema: a pool that loaded it before the last schema change reloads it first, and is recreated if it cannot.
      Parameters:
      url - the OrientDB connection URL
      username - the connection username (already unique per context/permission-mode/hierarchical-flag)
      password - the connection password
      Returns:
      the shared, possibly newly-created, ODatabasePool
    • recreatePool

      public static com.orientechnologies.orient.core.db.ODatabasePool recreatePool(String url, String username, String password)
      Closes and discards the current pool for the given username (if any), then creates and registers a fresh one. Used when a pool is suspected to be in a broken/closed state.
      Parameters:
      url - the OrientDB connection URL
      username - the connection username
      password - the connection password
      Returns:
      the freshly-created ODatabasePool
    • invalidatePool

      public static void invalidatePool(String username)
      Closes and removes the pool registered for the given username, if present. Safe to call even if no pool is currently registered for it.
      Parameters:
      username - the connection username whose pool should be invalidated
    • invalidatePoolsForContext

      public static void invalidatePoolsForContext(UUID contextUuid)
      Closes and removes every pool (reader/writer, hierarchical/non-hierarchical) associated with the given context UUID on every service instance in the deployment (via Redis pub/sub, see the class-level note on cross-instance invalidation) — not just this one. Intended to be called right after a structural mutation (reparent, ACL update) that could leave already-open pooled sessions holding stale permission state from before the mutation, forcing subsequent requests to establish fresh connections that pick up the updated permissions.
      Parameters:
      contextUuid - the UUID of the context whose pools should be invalidated
    • invalidateAllPools

      public static void invalidateAllPools()
      Closes and discards every pool currently registered on this instance, regardless of the context or permission mode it was created for. Local-instance only (no cross-instance broadcast, unlike invalidatePoolsForContext(UUID)) — intended for bulk, schema-mutating operations confined to a single instance (e.g. SystemRepository restoring a System Dump), where a global DDL change (new Types) can leave every pool in the JVM — not just one context's — holding a pre-mutation schema snapshot. Every subsequent Environment.getDatabaseDocument(PermissionMode) call, on any pool, opens a fresh physical connection that reads the current schema from storage.
    • discardPoolsAfterConnectionFailure

      public static boolean discardPoolsAfterConnectionFailure(Throwable failure)
      Discards every pool of this instance if the given failure, or one of its causes, is a connection to the database lost (an OIOException): after a database restart every pooled session holds a dead connection, and without this each of them would fail one request before being replaced. The request that met the failure is not repeated.
      Parameters:
      failure - the failure of a request
      Returns:
      true if the pools have been discarded