Repository navigation
Keep the legacy storage fingerprint for one release - #2118
Merged
ppXD merged 1 commit intoOct 18, 2026
Merged
Conversation
ppXD
force-pushed
the
fix/connect-oauth-without-a-public-base-url
branch
from
October 18, 2026 02:46
779546d to
142a062
Compare
Since namespaces were derived physically, admission, the agent-run-log bootstrap and the deployment-default materializer stored the hash of the provider's physical projection rather than the hash of the configuration as written. This build never decides on that column, but the previous build's retention reaper does: it treats one object key as one object across teams only when the revisions' stored fingerprints match. During a rolling deploy, or after a rollback, that reaper saw a revision this build admitted for 'R/' (or an OSS -internal or https endpoint, or an explicit region) as another namespace than one it had admitted for the same text, and collected another team's live bytes. New revisions store the legacy value again for one release, through StorageProfileRules.StoredNamespaceFingerprint. The physical projection is still taken, so a configuration that reaches no namespace is refused as before, and the reaper keeps deriving the physical object at sweep time. A recurring backfill restores the legacy value on revisions a physical-identity build already wrote, and on any an older pod writes during the rollout. Revisions are immutable under a trigger, so the pass switches it off inside its own transaction and back on before it commits; no migration is needed. Storing the physical identity is a follow-up release, once no build that compares the column can run against the database. That change also deletes the backfill, and must remove its schedule with it: the worker registrar only adds recurring entries, so a deleted job class leaves StorageNamespaceFingerprintBackfillRecurringJob registered and every ten-minute tick fails to load its type. Remove the entry at worker boot with ICodeSpaceBackgroundJobClient.RemoveRecurringJobIfExists, or keep the job class as a no-op for one more release.
ppXD
changed the base branch from
fix/connect-oauth-without-a-public-base-url
to
main
October 18, 2026 02:47
ppXD
force-pushed
the
fix/keep-the-legacy-storage-fingerprint-for-one-release
branch
from
October 18, 2026 02:47
094ce5e to
a0eaee1
Compare
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.
Summary
Since Compare storage namespaces by physical location #2105, admission, the agent-run-log bootstrap and the deployment-default materializer stored the hash of the provider's PHYSICAL namespace projection in
storage_profile_revision.namespace_fingerprint. The previous build's retention reaper decides whether one object key is one object across teams by comparing that stored column (ArtifactRetentionReaper.cs:469-489at 583efb0). During a rolling deploy, or after a rollback, it therefore treated a revision admitted forR/as a different namespace from one admitted forR, and collected another team's live bytes. OSS-internalorhttpsendpoints and an explicit region had the same effect.For this release, new revisions store the legacy value again:
StorageProfileRules.StoredNamespaceFingerprintcallsLegacyNamespaceFingerprint, which matches the 583efb0 algorithm byte for byte. This applies at admission (StorageProfileService.cs:275, which the deployment-default materializer also goes through) and at the agent-run-log bootstrap (AgentRunLogStorageReadiness.cs:81).StorageNamespaceFingerprintBackfillRecurringJobruns every 10 minutes as a thin Job → Command → Service chain. It restores the legacy value on revisions that a physical-identity build already wrote, or that an older pod writes during the rollout. It disables the revision immutability trigger only inside its own transaction and turns it back on before commit, so no migration is needed.Follow-up release, not in this PR: switch the stored value to the physical identity once no build that compares the column can run against the database. That change deletes the backfill and must also remove its schedule, because the worker registrar only adds recurring entries and a deleted job class makes every tick fail with
JobLoadException. Do one of:ICodeSpaceBackgroundJobClient.RemoveRecurringJobIfExists("StorageNamespaceFingerprintBackfillRecurringJob")at worker boot, orThis is documented on
StorageProfileRules.StoredNamespaceFingerprintand on the job class.Test plan
StorageNamespaceLegacyFingerprintTests,StorageNamespaceFingerprintBackfillDispatchTests):ArtifactRetentionReaperFlowTests.PreviousBuild): the previous build's stored-column comparison, over two revisions this build admitted with different spellings of one root, now says shared, and physically distinct roots still compare as different.ArtifactRetentionReaperFlowTests.Namespaces): this build's reaper behaves as before.StorageNamespaceFingerprintBackfillFlowTests): the backfill restores the legacy value, is idempotent, leaves the table immutable again, and is safe on concurrent workers.StorageNamespaceFingerprintBackfillE2ETests):StorageNamespaceFingerprintBackfillRecurringJobentry through Hangfire.storage_profile_revision_enforce_immutabilitystays enabled.StorageNamespaceSharingE2ETestsand the rest ofCodeSpace.E2ETests.Storagepass (59/59).