-
Notifications
You must be signed in to change notification settings - Fork 2
Type System
Note: types are very much a work in progress. All this is subject to change.
Types are fundamental to the redesign. They're at the core of everything I'm striving for.
Mytosis defines a few base types. Everything else is built on those. They are:
string
number
boolean
-
pointer
(astring
+ the type of thing it points to) -
literal
(a literal primitive value) -
union
(represents one of a set of types) -
Composite
(an object whose fields are known in advance)
There's also a notion of a derivation
, a type derived from a primitive. For example, date
might be a derivation of a UTC-based ISO string.
These types can be mixed and matched in order to create some interesting type signatures. For example:
// An enum of strings
union([literal('online'), literal('offline')])
// A user-ish object
const User = Composite({ firstName: string, lastName: string })
// A nullable user
union([pointer(User), literal(null)])
Composite types are an internal mechanism - they won't be exposed to the end developer. Composites are used to define higher-level types such as Registers and Records. When you define a new Register, it wraps the type information with extra metadata internal to the CRDT:
const createRegister = valueType => Composite({
type: string,
clock: number,
value: valueType,
})
In addition, if you pass a reference to another Register or Record, it'll replace that reference with a pointer. But that has nothing to do with the type system. I'm getting off topic.
This is where stuff gets interesting! There's a high likelihood that you'll change your schema at some point in the future. Migrations help you do that.
Migrations are applied in a set. If any migration fails, it rolls back to the original value. Each set of migrations bumps a migration version number by 1 (you might've seen type@version
in some other wiki pages).
There's one major limitation: you can't define your own migration operations in code. You have to pick from the list of supported operations.
Here's the list of supported migrations:
- Add field (requires a default value)
- Remove field (deletes the data too)
- Change type of field (coerces any existing data into the new type)
- Rename field (moves data along with it)
Since you have no immediate consistency guarantees, there aren't any cross-type migrations. You can't move something from one "table" to another, you can only rename it. There might be safe ways around this. I haven't thought of them yet.