Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/docs/(overview)/devices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Sometimes a copy can't be brought up to date, and has to be filled again by a hy

The hydration **empties the copy first** if the instance's event log now ends before the point the copy had reached, or before the point where a stopped hydration started, as it does on an instance restored from a backup, because the copy may hold versions the restored instance never had. It also does so if the hydration finds another instance at the address or a credential whose reach changed. The copy stops being `stale` at once, even if that hydration then fails, and it does the same when the instance refuses the hydration because the credential has ended or its reach changed, so it never answers rows the credential can no longer read. A hydration that fails for another reason, such as the instance being unavailable, leaves the copy `stale`.

**For any other reason, the copy refuses reads and writes until a hydration, which empties it first.** Examples are another instance answering at the same address, or a credential whose reach changed.
**For any other reason, the copy refuses reads and writes until a hydration, which empties it first.** Examples are another instance answering at the same address, or a credential whose reach changed. A device's own change of an item's type or move of an edge's source, once the server takes it, also changes the reach: the device sends the writes queued behind it, then expires the copy once.

A copy made by an earlier build of the core can have a different shape. The device **refuses to open it** with `wrong_schema`, deletes nothing, and says how many writes the file holds that the server hasn't taken, because only the build that made it can send them. If some are of a kind the current build no longer sends, it names the kind. [Troubleshooting](/run/troubleshooting#staying-in-step) says what to do. An app built on the core's Node or Swift binding can replace a refused copy that holds nothing unsent with an empty one; the files the copy downloaded and the file budget's setting stay. A [folder](/run/sync-a-folder#move-to-a-newer-cli) can replace its own copy itself.

Expand Down
2 changes: 1 addition & 1 deletion content/docs/(reference)/swift-sdk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ Besides `items`, the copy has `edges` (`from`, `to`, `ofType`, `get` for one ID
| `conflictedCopies(of:)`, `original(ofConflictedCopy:)` | An item's held conflicted copies, and the ID of the item a copy was made from. |

- **Read `title` and `body`** rather than `properties`: they read the properties the item's type uses for them. Where `properties` is empty, `unreadableProperties` says why: the copy holds properties that aren't JSON, aren't an object, or nest more than 64 levels deep, counting the properties object.
- **An `Edit` changes the properties it names.** With `replaceProperties: true`, they become the item's whole set.
- **An `Edit` changes the properties it names.** With `replaceProperties: true`, they become the item's whole set. With `type`, it changes the item's type. Once the server accepts a change of type, the copy expires, so hydrate again.
- **A `Draft` takes every field a create takes.** Besides the type and the properties, it carries `state` (`.active`, `.archived` or `.trashed`; `.revoked` is refused), `captureLatitude` with `captureLongitude`, and `edges`, a dictionary from an edge type to the IDs of the items it points at. An `Item` reads the capture location back in the same two properties.
- **A create is one write.** Its state, location and edges go in the body of the write that creates the item. If the instance refuses any edge, for example because a target doesn't exist, it creates neither the item nor its edges, and the write stays in the queue as refused. The copy shows each edge at once, and an empty list for an edge type queues no edge. An edge may point at an item that is still waiting to be created: the write waits for that create. If that create lands on an item the instance already holds, because the two share a source and a `sourceId`, the edge points at the item the instance holds.
- **An `Edit` sets or clears the item's own time.** `occurredAt` sets it, and `clearOccurredAt: true` gives the item no time of its own, so it sits at its creation time. The two can't be combined. Clearing the time of an item whose create hasn't been sent removes it from the create, and the copy shows the time the create was queued until the instance answers.
Expand Down
4 changes: 2 additions & 2 deletions content/docs/run/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,14 @@ Start over as you did the first time: read your data again from the API, and fol
</Accordion>
<Accordion title="409 reach_changed">

What your credential may read has changed since the working copy was built, for example because its key was narrowed. The copy can't be resumed, because what it holds no longer matches what the credential reads.
What your credential may read has changed since the working copy was built, for example because its key was narrowed or an item was moved to another type. The copy can't be resumed, because what it holds no longer matches what the credential reads.

Build the working copy again. [Devices](/devices) explains when a copy has to start over.

</Accordion>
<Accordion title="this working copy can no longer be kept current: …; rebuild the copy from the server">

This is how the CLI's device commands report `catchup_too_old` and `reach_changed`, with the code `copy_expired` and exit code `4`. Writes waiting in the queue are kept.
This is how the CLI's device commands report `catchup_too_old` and `reach_changed`, with the code `copy_expired` and exit code `4`. Writes waiting in the queue are kept. A device that sends a change of an item's type, or a move of an edge's source, that the server takes sends the writes queued behind it and then reports `reach_changed`, once. If the drain also meets a wait or an outage, it returns that report first, and the next call reports `reach_changed`.

Run `marfa device hydrate` again. After `catchup_too_old`, `marfa device status` reports the copy's hydration as `stale`, and the copy keeps answering reads, marked `stale`, while the hydrate fills it in place. Until the hydrate finishes, `marfa device drain` and `marfa device catch-up` keep answering `copy_expired` with `catchup_too_old`. If the credential no longer reads one of the types you held, leave that type out of `--types`, or the hydrate is refused with `type_not_permitted`.

Expand Down
Loading