Skip to content

feat(pj_datastore): add ObjectStore::findTopic(dataset_id, name)#84

Merged
pabloinigoblasco merged 1 commit intomainfrom
feat/object-store-find-topic
May 6, 2026
Merged

feat(pj_datastore): add ObjectStore::findTopic(dataset_id, name)#84
pabloinigoblasco merged 1 commit intomainfrom
feat/object-store-find-topic

Conversation

@pabloinigoblasco
Copy link
Copy Markdown
Collaborator

Summary

Add a pure-lookup API to ObjectStore:

std::optional<ObjectTopicId>
ObjectStore::findTopic(DatasetId, std::string_view) const noexcept;

Returns the existing handle if a topic with the given (dataset_id, topic_name) is registered, nullopt otherwise. Does not mutate the store.

registerTopic keeps its strict semantics: it still returns unexpected("topic already registered: ...") when a duplicate is attempted. Callers that need find-or-register semantics compose the two explicitly.

Why

pj_datastore/docs/OBJECT_STORE_DESIGN.md documents the responsibility split:

  • DataSource plugins register object topics on the source-side path (pj.source_object_write.v1).
  • Host runtime resolves an existing id when binding parser-side write surfaces (pj.parser_object_write.v1).

In other words: the source owns registration; the host looks up.

Until now the host had no lookup-only API, so it called registerTopic from its parser-binding flow. When a source had already registered the same topic via its own service, the second caller failed with "topic already registered: ...", the source-side pushLazy path went silently unwired, and blob channels lost retention.

findTopic lets the host honour the documented contract: bind to an existing id without creating one.

Diff

File Change
pj_datastore/include/pj_datastore/object_store.hpp declare findTopic
pj_datastore/src/object_store.cpp implement (std::shared_lock on the store mutex; linear scan over topics_ keyed by (dataset_id, name), same shape as registerTopic's duplicate check)
pj_datastore/tests/object_store_test.cpp two new tests (see below)

Total: +32 / −0 across 3 files.

Tests

  • FindTopicReturnsRegisteredId — happy path lookup after register.
  • FindTopicMissingReturnsNullopt — explicit miss returns nullopt.
  • DuplicateRegistrationFails (existing) is left untouched — registerTopic's strict contract is preserved.

Backward compatibility

Pure addition. Existing callers of registerTopic are unchanged. No semantic changes to existing APIs.

Add a pure-lookup API to `ObjectStore`:

  std::optional<ObjectTopicId>
  ObjectStore::findTopic(DatasetId, std::string_view) const noexcept;

Returns the existing handle if a topic with the given
`(dataset_id, topic_name)` is registered, `nullopt` otherwise. Does not
mutate the store.

`registerTopic` keeps its strict semantics: it still returns
`unexpected("topic already registered: ...")` when a duplicate is
attempted. Callers that need find-or-register semantics compose the
two explicitly.

Why
---
`OBJECT_STORE_DESIGN.md` documents that DataSource plugins register
object topics on the source-side path (`pj.source_object_write.v1`),
and host-side runtime code resolves an existing id when binding parser-
side write surfaces (`pj.parser_object_write.v1`) — i.e. the source
owns registration; the host looks up.

Without a lookup-only API the host had to call `registerTopic` from its
parser-binding flow. When a source had already registered the same
topic via its own service, the second caller failed with
`"topic already registered: ..."`, the source-side `pushLazy` path went
silently unwired, and blob channels lost retention.

`findTopic` lets the host honour the documented contract: bind to an
existing id without creating one.

Tests
-----
- `FindTopicReturnsRegisteredId` — happy path lookup after register.
- `FindTopicMissingReturnsNullopt` — explicit miss returns nullopt.
- `DuplicateRegistrationFails` (existing) is left untouched —
  `registerTopic`'s strict contract is preserved.
@pabloinigoblasco pabloinigoblasco merged commit 1d504df into main May 6, 2026
2 checks passed
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.

1 participant