Skip to content

proxystore.store.registry

Registry of the stores in a process.

Every Store registers itself in the module-level registry when it is created and unregisters itself when it is closed. Stores are keyed by their unique id, so a proxy resolved in the same process as the store which made it reuses that store, and proxies of a store from another process share one new store.

Stores which are not the owner of their objects, such as the stores made when resolving proxies, are closed when the process exits so that their connectors release any resources (e.g., sockets). These stores never clear the objects of their connector.

Most code does not need this module. Use get_store() or get_or_create_store() instead.

registry module-attribute

registry = StoreRegistry()

Registry of the stores in this process.

StoreRegistry

StoreRegistry()

Registry of stores keyed by store ID.

This class is thread-safe. Making a new store in get_or_create() does not block threads that look up or make other stores.

Source code in proxystore/store/registry.py
def __init__(self) -> None:
    self._stores: dict[str, Store[Any]] = {}
    # Only held to read or change _stores and _create_locks, never
    # while a store is being made.
    self._lock = threading.Lock()
    # One lock per store ID, held while get_or_create() makes that
    # store, so threads that need the same store make it only once.
    # Locks are never removed because a process only sees a few IDs.
    self._create_locks: dict[str, threading.Lock] = {}
    # IDs of stores whose owner was closed and removed their objects.
    self._closed: set[str] = set()

clear

clear() -> None

Unregister all stores without closing them and forget closed IDs.

This is mainly useful for resetting the registry between tests.

Source code in proxystore/store/registry.py
def clear(self) -> None:
    """Unregister all stores without closing them and forget closed IDs.

    This is mainly useful for resetting the registry between tests.
    """
    with self._lock:
        self._stores.clear()
        self._closed.clear()
    logger.debug('Cleared the store registry')

get

get(store_id: str) -> Store[Any] | None

Get the registered store with an ID.

Returns:

  • Store[Any] | None –

    The store or None if no store with the ID is registered.

Source code in proxystore/store/registry.py
def get(self, store_id: str) -> Store[Any] | None:
    """Get the registered store with an ID.

    Returns:
        The store or `None` if no store with the ID is registered.
    """
    with self._lock:
        return self._stores.get(store_id)

is_closed

is_closed(store_id: str) -> bool

Check if the ID of a store is closed.

The ID of a store is closed when the owner of the store is closed and its connector removes the stored objects. A store made with the Store constructor with the same ID opens the ID again.

Source code in proxystore/store/registry.py
def is_closed(self, store_id: str) -> bool:
    """Check if the ID of a store is closed.

    The ID of a store is closed when the
    [`owner`][proxystore.store.base.Store.owner] of the store is closed
    and its connector removes the stored objects. A store made with the
    [`Store`][proxystore.store.base.Store] constructor with the same ID
    opens the ID again.
    """
    with self._lock:
        return store_id in self._closed

get_or_create

get_or_create(config: StoreConfig) -> Store[Any]

Get the registered store with the ID in config or make one.

The new store registers itself in the module-level registry and is not the owner of the objects stored by its connector.

Parameters:

  • config (StoreConfig) –

    Store configuration. If config does not contain an ID, a new store with a new ID is always made.

Returns:

Raises:

Source code in proxystore/store/registry.py
def get_or_create(self, config: StoreConfig) -> Store[Any]:
    """Get the registered store with the ID in `config` or make one.

    The new store registers itself in the module-level
    [`registry`][proxystore.store.registry.registry] and is not the
    [`owner`][proxystore.store.base.Store.owner] of the objects stored
    by its connector.

    Args:
        config: Store configuration. If `config` does not contain an
            ID, a new store with a new ID is always made.

    Returns:
        Store instance.

    Raises:
        StoreClosedError: If the ID in `config` is
            [closed][proxystore.store.registry.StoreRegistry.is_closed].
    """
    # base.py imports this module so Store is imported here.
    from proxystore.store.base import Store

    if config.id is None:
        return Store.from_config(config, owner=False)

    with self._lock:
        store = self._get_open(config.id)
        if store is not None:
            return store
        create_lock = self._create_locks.setdefault(
            config.id,
            threading.Lock(),
        )

    with create_lock:
        # Another thread may have made or closed the store while this
        # one waited.
        with self._lock:
            store = self._get_open(config.id)
        if store is not None:
            return store

        new_store = Store.from_config(config, owner=False)
        registered = self.get(config.id)
        if registered is None or registered is new_store:
            return new_store

        # A store with this ID was made directly with the Store
        # constructor while the connector was being built. Use the
        # registered store so every caller gets the same instance.
        new_store.close()
        return registered

register

register(store: Store[Any]) -> None

Register a store.

Note

Stores register themselves when created so this does not need to be called.

If a store with the same ID is already registered, that store stays registered and store is ignored. Registering a store opens its ID again if the ID was closed.

Source code in proxystore/store/registry.py
def register(self, store: Store[Any]) -> None:
    """Register a store.

    Note:
        Stores register themselves when created so this does not need
        to be called.

    If a store with the same ID is already registered, that store stays
    registered and `store` is ignored. Registering a store opens its ID
    again if the ID was closed.
    """
    with self._lock:
        self._closed.discard(store.id)
        if store.id not in self._stores:
            self._stores[store.id] = store
            logger.debug('Registered %r', store)

unregister

unregister(
    store: Store[Any], *, closed: bool = False
) -> None

Unregister a store.

Note

Stores unregister themselves when closed so this does not need to be called.

Nothing happens if a different store with the same ID is registered.

Parameters:

  • store (Store[Any]) –

    Store to unregister.

  • closed (bool, default: False ) –

    Also close the ID of the store, so proxies of the store cannot be resolved in this process.

Source code in proxystore/store/registry.py
def unregister(self, store: Store[Any], *, closed: bool = False) -> None:
    """Unregister a store.

    Note:
        Stores unregister themselves when closed so this does not need
        to be called.

    Nothing happens if a different store with the same ID is
    registered.

    Args:
        store: Store to unregister.
        closed: Also close the ID of the store, so proxies of the store
            cannot be resolved in this process.
    """
    with self._lock:
        if closed:
            self._closed.add(store.id)
            logger.debug('Closed store ID %s', store.id)
        if self._stores.get(store.id) is store:
            del self._stores[store.id]
            logger.debug('Unregistered %r', store)