Repository navigation
feat(accounts): the object-storage datasource provider is resolved from the composed service, not compiled into the registry - #1269
Draft
antoinetoussaint-byte wants to merge 1 commit into
Conversation
…om the composed service, not compiled into the registry The connector registry is built with the compiled-in providers only (github, api, crawler). Object storage is registered through Registry.Register, wrapped in connector.Budgeted, when the declared object-storage dependency resolves to a service that can read a bucket (SetObjectStorage). A composition without that service has no upload entry in the catalog, and AddSource and sync refuse a source of it by name. Everything the host does for the provider moves to datasource_objectstore.go; datasources.go no longer imports objectstore, and the sync batches by the registered descriptor's budget. The conformance suite also runs against the connector the registry holds. Closes #1268 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1268.
Stacked on #1235, draft until it merges. The base is #1235's branch, so the diff shows only this change. Once #1235 merges, this gets rebased onto
main, retargeted, and its checks counted on the SHA that will merge. CI does not run on a stacked PR (ci.ymltriggers onpull_request: branches: [main]), so for now the evidence is the local runs below.What changes
github(conformant),apiandcrawler(non-conformant with their gap). Object storage is no longer one of them.SetObjectStorageregisters object storage, and only afterobjectstore.CheckServicehas confirmed that the composed service can serve a per-call binding with a batched read.work.gocalls it once the declaredobject-storagedependency resolves. Registration usesRegistry.Register's own validation and wraps the connector inconnector.Budgeted.uploadentry;AddSource(upload)fails withFailedPreconditionandErrObjectStorageUnavailable, i.e. by name, not as an unknown provider;DatasourceConformancegives that same sentence as the source's gap.pkg/business/datasource_objectstore.go. That covers the setters, registration, per-call bucket resolution, retained listings,runUploadSyncand the park step; the code is moved, not rewritten.datasources.goanddatasource_connectors.gono longer importobjectstore. The sync now sizes its batches from the registered descriptor'sBudget(MaxItemsPerCall/MaxBytesPerCall) rather than from package constants. The values are the same.github,apiandcrawlerare unchanged. The four provider constants stay.Envelope
datasourceScheduleroverdatasource_credential_budgetsmeters across every source and replica, and the composed service never sees it.Reused, and deliberately not
Reused:
Registry.Registerand its descriptor validation,Descriptor,connector.Budgetedwith the host'sdatasourceScheduler,connectortest.RunFiles, #1235'sobjectstore.CheckService/ServiceBucketclient, and the existingdialObjectStorageresolution of the declared dependency.Deliberately not built: a provider resolver, a table of composed providers, a manifest field or any other second mechanism. With one composed provider, the seam is "the dependency resolves, so
Register". A generic list would only be justified by a published provider contract, which is step 1 after this issue.Fix or hack
Fix, at the owner: the host's build no longer decides whether object storage exists. Composition does. No stopgap.
Docs (same PR)
module/services/accounts/AGENTS.md: a new section, A datasource provider is compiled in, or resolved from a composed service. The object-storage admission bullet is rewritten to match.module/services/accounts/code/pkg/datasource/connector/CONFORMANCE.md: object storage is registered through its service, the suite runs as registered, and registration needs a capable service.module/services/README.md: the provider exists only whereobject-storageis composed. The topology itself is unchanged; feat(accounts): object-storage sources read through the composed object-storage service; the host's store client is deleted #1235 already composes the service.module/DEPLOYMENT_TOPOLOGY.mdneeds no change.Tests
TestObjectStorageAsRegisteredPassesTheConformanceSuite. It runsconnectortest.RunFilesagainstDatasourceConnectors().Files("upload")after the provider is resolved, on sources connected throughAddSource. That exercises the credential the host decrypts per call and the listings retained in the host's store. 14 cases pass and case 05 is skipped, the same as the package-level run (readers are source-scoped).TestObjectStorageIsAdmittedOnlyWhereAServiceCanReadItis nowTestObjectStorageIsRegisteredOnlyWhereItsServiceResolves. It checks that the provider is absent from the catalog, thatAddSourcerefuses it by name, that the conformance gap names it, and that the provider is present and admitted once resolved. The 0.0.18-service admission test now expects the provider to be absent rather than listed but refusing.go test -tags pure ./pkg/business/ ./pkg/datasource/...passes.go test -p 1 ./pkg/business/ ./pkg/adapters/passes (DB-backed, store and vault booted by codefly v0.1.215).go vetis clean.goimports -lis clean.golangci-lintreports nothing new in the touched files. TheoperationsOnlyunused field already exists at feat(accounts): object-storage sources read through the composed object-storage service; the host's store client is deleted #1235's head.scripts/check-boundaries.share clean.Run first: the three behaviours, from
codefly runI used codefly v0.1.215, the CI pin (darwin-arm64 archive, digest checked against the release's
checksums.txt). The local development CLI fails at accounts runtime-init withno configuration found for egress. I logged in through the gateway with the dev-admin fixture (/v1/auth/authenticate) and called Connect on the gateway's REST port.Composed:
codefly run service saas-starter/auth-gateway --fixture dev-admin --headless --temporary-ports→Will run 6 service(s): … saas-starter/object-storage@0.0.0 via codefly.dev/object-storage:0.0.19 …Not composed: the same command with
--exclude-dependency saas-starter/object-storage→Will run 5 service(s)(no object-storage). Accounts logsthe composed object-storage service cannot read a tenant's bucket; object-storage datasources are unavailable error=… dial tcp 127.0.0.1:52123: connect: connection refused.Not verified
codefly ci run(the canonical service gate) was not run locally. CI will run it after the rebase ontomain.DatasourceConformance, and the sync'sErrObjectStorageUnavailable). It was not exercised at runtime: each--temporary-portsrun gets its own state, so the source created in the composed run was not visible to the excluded run.--exclude-dependency saas-starter/object-storage, accounts still resolved an endpoint address for the excluded service, and the dial was refused. The host's behaviour is correct either way: no address, or a service that cannot answer, both leave the provider unregistered. But the absent run went through the "cannot read" branch, not the "no object-storage service is composed" branch. Whether the CLI should export an endpoint for an excluded dependency is a question for codefly-dev/cli. I have not filed it.🤖 Generated with Claude Code