Conversation
|
|
||
| **Promote the contract package to `platform/`.** Rejected under Decision 5. | ||
|
|
||
| ## Worth considering afterwards: relocating `submitqueue/core/` |
There was a problem hiding this comment.
Could take the same approach for 'core/'. not necessary now, but might worth considering once this lands.
fcd6c7f to
ead85cc
Compare
| @@ -0,0 +1,89 @@ | |||
| # Service-Scoped Extensions | |||
|
|
|||
| Moving an extension used by exactly one service of a multi-service domain out of `{domain}/extension/` and into `{domain}/{service}/extension/`, so the service and the thing it depends on map one to one. SubmitQueue's storage extension goes first; the layout rule is meant to apply to every extension after it. | |||
There was a problem hiding this comment.
Agent-written.
Decision 1 already covers more than storage: changeprovider, validator, conflict, buildrunner, and speculation are orchestrator-only today. Say whether they stay at {domain}/extension/ until a later RFC, or only extensions with a schema split move. Implementation also needs the new path in AGENTS.md.
queueconfig is gateway-only now but expected in both services — leave it at submitqueue/extension/queueconfig/.
|
|
||
| > The gateway owns the append-only request log and three new logical read models. The orchestrator's request and change stores are pipeline working state with different retention semantics, so neither API reads them. | ||
|
|
||
| Nothing enforces it. A gateway controller can resolve `BatchStore` and nothing objects. Deployments feel it too: the MySQL schema is one filegroup, so a deployment that gives each service its own database provisions all thirteen tables in both, including the nine or four the service never reads. |
There was a problem hiding this comment.
Agent-written.
Separate DBs already work: orchestrator publishes logs on the queue; gateway persists them. The four gateway tables are not a shared store.
|
|
||
| 1. An extension used by exactly one service of a multi-service domain lives at `{domain}/{service}/extension/{ext}/`, with its implementations, mocks and schema underneath it, exactly as a domain-level extension does today. | ||
| 2. An extension genuinely shared between a domain's services stays at `{domain}/extension/{ext}/`. A single-service domain is unaffected: its domain root is its service root, so nothing moves. | ||
| 3. SubmitQueue's storage extension splits into `submitqueue/gateway/extension/storage/` and `submitqueue/orchestrator/extension/storage/`. Each declares its own `Factory` and its own `Storage` aggregate covering only its stores. |
There was a problem hiding this comment.
Agent-written.
Split Factory/Storage by service. Keep store interfaces in submitqueue/extension/storage/. Moving *_store.go forces core/ to import a service package in this refactor, not later.
| 1. An extension used by exactly one service of a multi-service domain lives at `{domain}/{service}/extension/{ext}/`, with its implementations, mocks and schema underneath it, exactly as a domain-level extension does today. | ||
| 2. An extension genuinely shared between a domain's services stays at `{domain}/extension/{ext}/`. A single-service domain is unaffected: its domain root is its service root, so nothing moves. | ||
| 3. SubmitQueue's storage extension splits into `submitqueue/gateway/extension/storage/` and `submitqueue/orchestrator/extension/storage/`. Each declares its own `Factory` and its own `Storage` aggregate covering only its stores. | ||
| 4. `submitqueue/extension/storage/` survives as a contract-only package: the error vocabulary and `Config`, which both halves and `submitqueue/core/` depend on. It keeps its import path, so nothing that uses only those symbols changes. |
There was a problem hiding this comment.
Agent-written.
ErrNotFound/Config callers stay. Materializer and TerminateRequest take Factory/Storage and will change. The storage README belongs with the interfaces.
| 3. SubmitQueue's storage extension splits into `submitqueue/gateway/extension/storage/` and `submitqueue/orchestrator/extension/storage/`. Each declares its own `Factory` and its own `Storage` aggregate covering only its stores. | ||
| 4. `submitqueue/extension/storage/` survives as a contract-only package: the error vocabulary and `Config`, which both halves and `submitqueue/core/` depend on. It keeps its import path, so nothing that uses only those symbols changes. | ||
| 5. The contract package is not promoted to `platform/`. It is not cross-domain — `stovepipe/extension/storage/storage.go` already declares its own verbatim copy of the same symbols, so a per-domain error vocabulary is the existing pattern rather than something this RFC introduces. | ||
| 6. Each half owns its own MySQL schema directory, so the tables a service creates are the tables it reads. |
There was a problem hiding this comment.
Agent-written.
Keep a union schema for colocated DBs (e2e, local compose), as #737 did. Split schemas are the opt-in for separate DBs.
|
|
||
| ## Worth considering afterwards: relocating `submitqueue/core/` | ||
|
|
||
| Not part of this refactor, and nothing here depends on it. Raising it because the split makes an existing oddity visible, and the cheapest moment to act on it is while the surrounding code is already being touched. |
There was a problem hiding this comment.
Agent-written.
If interfaces move with Decision 3, core/ has no domain Storage to import. That is in scope, not a follow-on.
|
|
||
| So the suggestion is to move `core/batch` and `core/changeset` under the orchestrator, and split `core/request` by file. It would be mechanical: the files already divide along the line, and rebinding them has already proven where each one belongs. | ||
|
|
||
| A smaller observation in passing. `core/request/request.go` holds `CurrentState` and `GetCurrentStateFromRequestLog`, and neither has a caller outside that file's own tests. It is an exported symbol in a domain-internal package, so it is not API anyone outside the repository depends on. If that is genuinely dead, deleting it removes the third file from the `core/request` question and leaves two going opposite directions. Worth confirming rather than assuming. |
There was a problem hiding this comment.
Agent-written.
Confirmed unused. Drop from this RFC; delete in its own PR.
|
Agent-written. Layout No store is shared today. A later shared store: interface in
|
behinddwalls
left a comment
There was a problem hiding this comment.
Agent-written.
Requesting changes: split Factory/Storage by service, but keep store interfaces in submitqueue/extension/storage/. Moving *_store.go inverts core/ and is in scope for this RFC. queueconfig stays domain-level (shared). Preserve a colocated schema union.
ead85cc to
ce8de6d
Compare
ce8de6d to
c5ec2dc
Compare
|
@behinddwalls Stack now uses your layout. contracts and their mocks stay at But still one more concern. Splitting contract from implementation costs some cohesion. a table's interface now sits in a different tree from its MySQL code and its Went with yours anyway because it avoids the inversion now. moving the contracts to service level only becomes clean after the other extensions refactor lands and so imo if the store sets stay disjoint indefinitely and the extensions move is definitely happening, cohesion wins and it's worth revisiting before this is entrenched. otherwise I'm happy here. |
c5ec2dc to
73eb649
Compare
…torage per service
73eb649 to
5051dde
Compare
Why?
Both SubmitQueue services depend on one thirteen-store
Storageaggregate, so a gateway controller can resolveBatchStoreand nothing objects. The split is already the documented design —status-list-api.mdsays the gateway owns the request log and three read models, and the orchestrator's stores are pipeline working state — but nothing expresses it.Separating the services onto their own databases already works today; what does not is provisioning. The schema is one filegroup, so each database gets all thirteen tables, including the nine or four that service never reads.
What?
An RFC for the layout rule: when only one service of a multi-service domain resolves an extension, its
Factory, aggregate, implementations, mocks and schema move to{domain}/{service}/extension/{ext}/, while the behaviouralcontracts stay shared.
The split is on reachability, not declaration — what a service may resolve is decided by its aggregate's accessors, so that is the part worth scoping. Moving the contracts too would add no enforcement and cost every domain-level caller a dependency on a service package.
Scope is storage only.
changeprovider,validator,conflict,buildrunnerandspeculationare orchestrator-only and would qualify, but none has a schema and none is the reason for this change; they wait for a later RFC.queueconfigstays shared — gateway-only today, expected in both.Test Plan
Issue