Skip to content

Registry: Add Store class to support multiple Registry backends#379

Draft
AgentDosaku wants to merge 8 commits intodevfrom
feat/store-multi-registry
Draft

Registry: Add Store class to support multiple Registry backends#379
AgentDosaku wants to merge 8 commits intodevfrom
feat/store-multi-registry

Conversation

@AgentDosaku
Copy link
Collaborator

@AgentDosaku AgentDosaku commented Feb 26, 2026

Summary

This PR implements a new Store abstraction that wraps multiple Registry instances behind one API.

What was added

  • Store and StoreMount implementation:
    • mindtrace/registry/mindtrace/registry/core/store.py
  • New Store-specific exceptions:
    • StoreLocationNotFound
    • StoreKeyFormatError
    • StoreAmbiguousObjectError
  • Public exports from mindtrace.registry for Store classes/exceptions.
  • Config support for default Store local path:
    • MINDTRACE_DIR_PATHS.STORE_DIR
    • default in config.ini: ${MINDTRACE_DIR_PATHS:ROOT}/store
  • Unit tests for Store behavior:
    • tests/unit/mindtrace/registry/core/test_store.py
  • Design document:
    • docs/storage/store-design.md

Implemented behavior

  • Store() defaults to a local mount (default) backed by config-driven STORE_DIR.
  • load("name") (unqualified) performs cross-mount discovery.
  • load("location/name") (qualified) only checks the specified mount.
  • If unqualified load finds multiple matches, raises StoreAmbiguousObjectError listing locations.
  • Local name→location cache is used to prioritize discovery probes.
  • save and delete require qualified keys (<location>/<name>) to prevent accidental writes/deletes.

Design Doc

Reviewer copy/paste examples

1) Two local registries + explicit writes

from pathlib import Path
from mindtrace.registry import Registry, Store

r1 = Registry(backend=Path("/tmp/store_a"), version_objects=True, mutable=True)
r2 = Registry(backend=Path("/tmp/store_b"), version_objects=True, mutable=True)

store = Store(mounts={"a": r1, "b": r2}, default_location="a")

store.save("a/model:resnet", {"acc": 0.92})
store.save("b/model:vit", {"acc": 0.95})

print(store.load("a/model:resnet"))
print(store.load("b/model:vit"))

2) Unqualified load discovery

from pathlib import Path
from mindtrace.registry import Registry, Store

r1 = Registry(backend=Path("/tmp/store_a"), version_objects=True, mutable=True)
r2 = Registry(backend=Path("/tmp/store_b"), version_objects=True, mutable=True)

store = Store(mounts={"a": r1, "b": r2})
store.save("b/data:item1", "hello")

# No location specified -> Store checks mounts and finds b/data:item1
print(store.load("data:item1"))

3) Ambiguity handling

from pathlib import Path
from mindtrace.registry import Registry, Store
from mindtrace.registry.core.exceptions import StoreAmbiguousObjectError

r1 = Registry(backend=Path("/tmp/store_a"), version_objects=True, mutable=True)
r2 = Registry(backend=Path("/tmp/store_b"), version_objects=True, mutable=True)

store = Store(mounts={"a": r1, "b": r2})
store.save("a/shared:item", 1)
store.save("b/shared:item", 2)

try:
    store.load("shared:item")
except StoreAmbiguousObjectError as e:
    print("Ambiguous as expected:", e)

# explicit location works
print(store.load("a/shared:item"))

4) Default local Store with no mounts provided

from mindtrace.registry import Store

store = Store()  # creates location="default" at MINDTRACE_DIR_PATHS.STORE_DIR
store.save("default/demo:item", {"ok": True})
print(store.load("default/demo:item"))

Testing

  • pytest -q tests/unit/mindtrace/registry/core/test_store.py
  • ds test --unit

Closes #279

@AgentDosaku AgentDosaku changed the title feat(registry): add Store facade for multi-registry backends Registry: Add Store class to support multiple Registry backends Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a Store class that wraps multiple Registries together

1 participant