Repository navigation
GO-7567: 0.7.2 keep names reserved, never remove cache records - #62
Merged
Merged
Conversation
A name stays reserved to the identity that registered it. 0.7.1 turned a lapsed name into a tombstone with a ReplaceOne of a bare observation, which wiped its owner fields, and re-read the chain on lookups and on a time schedule, which exhausted the provider quota. - a lapse is stored on the record in place (lapsed, expiry, registry owner, block); the owner fields, AnyID, space ID and canon stay, no enrichment reads. a lapsed name that is not cached is not written - "never registered" never removes: the cached record stays (errNotOnChain, a settled refresh); the finalized-block confirmation and every tombstone write are gone - 0.7.1 tombstones (removed) are served as taken; the alias check counts them - lookups hand only refresh_needed records to the background; repair_at is due only for refresh_needed records and re-reads; the scan reschedules records due under the 0.7.1 rules without a chain read - exponential per-record failure backoff (refresh_failures, 1 min doubled, at most 24 h), reset by a successful write - maintenance: -release-name (support transfer), -restore-tombstones -restore-from (owners from a mongoexport), -rpc-url; -refresh-cache counts lapsed / not-on-chain; -purge-tombstones removed
AdminNameRegisterSigned looks the canonical name up in the cache before it sends the operation (cache.CheckReservation, on IsNameAvailable: any record, lapsed, removed or under another spelling). A record of another identity or without an owner is rejected (ErrNameReserved), the same identity is allowed (a re-registration after a lapse, the payment node's renew-past-grace fallback), a cache read error rejects (fail closed). GetDataNameRegister and GetDataNameRegisterForSpace check the same before building calldata for a client-signed registration. Renewals are not checked.
An incomplete read (and a name reserved without a registry owner) carries over from the stored record what it could not read: the owner, its wallet, AnyID and space ID. The record stays incomplete and marked until a complete read. In 0.7.2 the identity of a name only changes through our operations or -release-name, so a stored owner is never a guess.
The first scans after the upgrade reschedule thousands of records that are due only under the 0.7.1 rules. They no longer fill the batch: the scan pages on by (repair_at, _id), at most 500 reschedules per round, so a due re-read or incomplete record is still read in the same round.
A lagging provider must not consume an operation's re-reads. A cached record that the chain says was never registered keeps its due re-reads and backs off like a failed refresh (1, 2, 4... minutes, never every lease); after 6 such reads in a row (past the +30 min re-read) they are done and the record is left to an operator.
…ion poll burst - refreshAfterOperation stores the operation's re-reads itself when another refresh holds the record, so they survive a skipped or timed-out request schedule (bounded write in the worker, the poll never waits) - a replacing write keeps a short hold (refresh_next_at = read + lease): repeated GetOperation polls of a cached name no longer cost one chain refresh each
…unnormalizable -restore-tombstones: - name_expires is the later of the export's and the tombstone's - names with records of different owners in the export are not restored, listed as conflict: - skipped= counts records that were no longer removed at the write (tombstones = restored + skipped + missing + conflicts) - owner-differs: lists live records whose owner differs from the export's (for support; nothing is written); exit 1 on missing/conflict/owner-differs - a restore with name_expires 0 is logged -release-name deletes only the record as printed (_id, observed_at, owner_any_address); ErrRecordChanged if it changed in between. -refresh-cache counts names that can not be normalized as unnormalizable=, not as failed.
At startup of a maintenance run, eth_chainId of -rpc-url is compared with accountAbstraction.chainID of the config (or, without one, with the chain id of contracts.gethUrl); a mismatch or a failed read refuses to run. Errors carry the provider host only, never the URL.
…r, backups, rollback)
… marks, safer maintenance - an operation (its re-reads) cuts a failure backoff to refreshLease and resets refresh_failures, so a renewal shows soon after a provider outage - unreadOwner carries the owner over only for the same AnyID - a not-on-chain record past the retries is retired: its mark is cleared too - -restore-tombstones: a lapsed restore clears refresh_needed, refresh_failures and stale re-reads (no live chain read); an unknown expiry (0) gets refresh_needed instead of lapsed - a maintenance run never replaces a complete record with an incomplete read: it counts as failed
…nt, 0.6.9 rollback note, follow-ups)
Coverage provided by https://github.com/seriousben/go-patch-cover-action |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Linear: GO-7567 (hotfix for 0.7.1). Design:
doc/names-reserved-0.7.2.md.Problem
v0.7.1 made the name cache free names that lapsed on chain (tombstones). In prod this:
ReplaceOneof a bare observation), and made those names available to anyone;Summary
lapsed: true, expiry, block), keeping owner/AnyID/space; no enrichment reads. "Not registered" never removes a cached record (not-on-chain, bounded retries). No tombstones are written; existingremovedrecords are served as taken. Finality/removal machinery and-purge-tombstonesare gone.AdminNameRegisterSignedrejects a name cached for another (or no) identity (ErrNameReserved), fail closed; same owner allowed. Advisory check onGetDataNameRegister*.-restore-tombstones -restore-from <mongoexport jsonl>(restores owners of 0.7.1 tombstones; reports missing / conflict / owner-differs),-release-name <name>(support transfer),-refresh-cache -rpc-url <url>(one-off pass on another provider, chain id checked; no re-reads scheduled for the live nodes;lapsed/not-on-chain/unnormalizablecounters).-dedupe-cache.Rollout (README "Name cache")
-restore-tombstones -restore-from ns-cache-20261007.jsonl(export taken before 0.7.1), dry run then-refresh-apply.ns.cache, then-refresh-cache -rpc-url <alchemy> -refresh-interval 2s, dry run then-refresh-apply.Rollback: 0.6.9 (serves every record as taken). Never 0.7.1.
Test plan
go build ./...,gofmt -lclean;go vet/ errcheck+revive: no new findings vs v0.7.1go test -p 1 ./...on a replica set: all pass exceptcontracts TestNormalizeEnsip1(fails locally on v0.7.1 too, passes in CI)