Updated Proposal: application schema coordination and versioning (markdown)
parent
23a7f0b3a0
commit
08cb508b9c
1 changed files with 43 additions and 1 deletions
|
@ -82,7 +82,7 @@ This is similar to the 'user version' functionality in SQLite, with important di
|
|||
- The datom store's schema consists of `{name, version}` pairs, not a single version.
|
||||
- Schema fragments have a globally unique identifier, allowing them to be shared across applications.
|
||||
- Applications are made aware at runtime when schema fragments change.
|
||||
- Many schema changes -- adding attributes, altering indexing choices, or weakening constraints -- can be performed automatically with no need to supply migration code.
|
||||
- Many schema changes — adding attributes, altering indexing choices, or weakening constraints — can be performed automatically with no need to supply migration code.
|
||||
|
||||
Under this proposal different applications can each ship shared schema fragments, coordinate upgrades, avoid conflicts in a large majority of cases, and safely detect real conflicts when they arise.
|
||||
|
||||
|
@ -196,8 +196,48 @@ The schema handling code performs a sequence of operations:
|
|||
|
||||
Most migrations will be very simple — some per-fragment pre- or post-upgrade code, if that — but this sequence exists if more complicated changes are required. Note that each fragment has pre/post/rename stages, as does the application itself. This should allow for simpler code sharing, avoiding the need for schema fragments to accommodate application logic.
|
||||
|
||||
For example, an imaginary upgrade sequence for developers who made a bunch of errors in a previous release might be:
|
||||
|
||||
> From: page=2, save=1
|
||||
> To: page=3, save=2
|
||||
> - App 'pre': clean up old history so we don't have to fix it.
|
||||
> - Page 'pre': fix duplicate visits, prior to imposing a uniqueness constraint.
|
||||
> - Save 'pre': delete saves for pages that no longer exist, prior to imposing a component constraint.
|
||||
> - Page renames: none.
|
||||
> - Save renames: rename `:save/instant` to `:save/savedAt` to fix a copy-paste error.
|
||||
> - Page schema upgrade, 2->3: apply uniqueness constraint to `:page/visit`.
|
||||
> - Save schema upgrade, 1->2: set `isComponent` to `true` to avoid orphans when history is deleted.
|
||||
> - Page 'post': add inter-visit relationships to fixed pages using new vocabulary.
|
||||
> - Save 'post': none.
|
||||
> - App 'post': none.
|
||||
|
||||
Note that the page and save pre/rename/upgrade/post sequences are independent of each other and of the app sequence. Another application might share the page logic and perform this sequence first:
|
||||
|
||||
> From: page=2
|
||||
> To: page=3
|
||||
> - App 'pre': clean up old history so we don't have to fix it.
|
||||
> - Page 'pre': fix duplicate visits, prior to imposing a uniqueness constraint.
|
||||
> - Page renames: none.
|
||||
> - Page schema upgrade, 2->3: apply uniqueness constraint to `:page/visit`.
|
||||
> - Page 'post': add inter-visit relationships to fixed pages using new vocabulary.
|
||||
> - App 'post': none.
|
||||
|
||||
leaving our first application to only upgrade the save schema fragment:
|
||||
|
||||
> From: save=1
|
||||
> To: save=2
|
||||
> - Save 'pre': delete saves for pages that no longer exist, prior to imposing a component constraint.
|
||||
> - Save renames: rename `:save/instant` to `:save/savedAt` to fix a copy-paste error.
|
||||
> - Save schema upgrade, 1->2: set `isComponent` to `true` to avoid orphans when history is deleted.
|
||||
> - Save 'post': none.
|
||||
> - App 'post': none.
|
||||
|
||||
After commit, the app updates its caches and other metadata, secure in the knowledge that the entire migration happened atomically and was persisted to disk.
|
||||
|
||||
### Per-fragment options
|
||||
|
||||
Renames can be specified in the schema fragment itself:
|
||||
|
||||
```
|
||||
{:schema/name "org.mozilla.core.page"
|
||||
:schema/version 3
|
||||
|
@ -216,3 +256,5 @@ Most migrations will be very simple — some per-fragment pre- or post-upgrade c
|
|||
:db/doc "A visit to the page."
|
||||
:db.install/_attribute :db.part/db}]}
|
||||
```
|
||||
|
||||
Pre- and post-upgrade functions, of course, can't easily be specified declaratively. They should instead be functions `(f conn from to)` that only have side effects on the provided connection, and raise on error.
|
Loading…
Reference in a new issue