fix(autonumber): single owner = persistent driver sequence (#1603)#1608
Merged
Conversation
Autonumber values were generated twice: the SQL driver's persistent, atomic _objectstack_sequences table AND a non-persistent in-memory counter in the engine. The engine pre-filled before calling the driver, so the driver always saw a value and skipped — leaving the persistent sequence as dead code and risking duplicate numbers across instances / after a restart. - spec: DriverCapabilities.autonumber (optional) capability flag. - driver-sql: advertise supports.autonumber=true; bulkCreate now fills autonumber too (was create/upsert only); parse honors autonumberFormat OR format. - objectql: engine defers to the driver when it advertises native autonumber support (no more pre-fill / in-memory shadow); keeps the in-memory fallback for memory/mongodb; fallback also reads either format key; record-validation exempts autonumber from the required check (runtime-owned, assigned post-validation). Tests: driver bulkCreate + autonumberFormat + capability (driver-sql 140 pass); engine defer-vs-fallback + validator exemption (objectql 526 pass). Existing data respected via scanMaxNumericTail bootstrap. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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
Closes the #1603 "persistent autonumber sequence" gap by making autonumber generation single-owner.
Today autonumber values are generated in two places:
_objectstack_sequencestable (getNextSequenceValue/fillAutoNumberFields), andapplyAutonumbers).Because the engine pre-fills the field before calling the driver, the driver always sees a value already set and skips (
fillAutoNumberFieldsline ~618). So the persistent sequence is effectively dead code, and a multi-instance / post-restart deployment can mint duplicate numbers from the in-memory counter.Changes
@objectstack/specDriverCapabilitiesgains an optionalautonumberflag — "driver natively generates persistent autonumber/sequence values".@objectstack/driver-sqlsupports.autonumber = true.bulkCreate()now fills autonumber fields too — previously onlycreate()/upsert()did, so bulk inserts skipped the sequence.autonumberFormatkey or theformatshorthand (both appear in metadata). This prevents a format-loss regression now that the driver path is the live one.@objectstack/objectqlautonumberFormatorformat.autonumberfrom therequiredcheck — the value is runtime-owned and assigned after validation, so a required record number is never rejected as "missing".No metadata changes required. Existing data is respected — the driver bootstraps each sequence from the current max numeric tail on first use (
scanMaxNumericTail).Testing
bulkCreateautonumber fill, theautonumberFormatkey, and thesupports.autonumbercapability — plus the existing per-tenant / bootstrap / concurrency / global-sequence suite.engine-autonumber-defer.test.ts(native driver → engine does NOT pre-fill and never scans; non-native driver → engine fallback fills) andrecord-validator.test.ts(required autonumber missing → no error; required non-autonumber missing → error).Risk
This activates a previously-dormant-but-fully-tested driver path. The driver's
autoNumberFieldsmap is already populated in production viasyncSchema → initObjects, so generation does not silently stop. The format-key harmonization removes the one regression vector (metadata declaringautonumberFormat).🤖 Generated with Claude Code