SpiceDB Documentation
Concepts
Watching Changes

Watching Relationship Changes

The Watch API (opens in a new tab) in SpiceDB enables clients to monitor changes made to Relationships within the system.

Watch events are generated when relationships are created, touched, or deleted through the WriteRelationships (opens in a new tab), DeleteRelationships (opens in a new tab), or the bulk import API.

Subscribing to Watch

To subscribe to receive watch changes, the Watch API call is made:

watcher = client.Watch(WatchRequest{})
for resp in watcher:
  ... process the update ...

This will start returning all updates to relationships from the time at which the API call was made.

Receiving historical updates

Historical updates (i.e. relationship changes in the past) can be retrieved by specifying a ZedToken in the WatchRequest:

watcher = client.Watch(WatchRequest{
  OptionalStartCursor: myZedToken
})

Historical changes can only be requested until the configured garbage collection window on the underlying datastore. This is typically 24 hours, but may differ based on the datastore used.

Ensuring continuous processing

To ensure continuous processing, the calling client should execute the Watch call in a loop, sending in the last received ZedToken from ChangesThrough if the call disconnects:

while not_canceled:
  last_zed_token = None
  try:
    watcher = client.Watch(WatchRequest{
      OptionalStartCursor: last_zed_token
    })
    for resp in watcher:
      ... process the update ...
      last_zed_token = resp.ChangesThrough
  except Exception:
    ... log exception ...
    continue

Transaction Metadata

SpiceDB's WriteRelationships (opens in a new tab) and DeleteRelationships (opens in a new tab) APIs support an optional metadata block called the Transaction Metadata (opens in a new tab).

When optional_transaction_metadata is specified on the WriteRelationships (opens in a new tab) or DeleteRelationships (opens in a new tab) request, it will be stored and returned alongside the relationships in the Watch API:

client.WriteRelationships(WriteRelationshipsRequest{
  Updates: [
    { Relationship: "document:somedoc#viewer@user:tom" }
  ],
  OptionalTransactionMetadata: {
    "request_id": "12345"
  }
})
 
...
 
WatchResponse{
  Updates: [
    { Relationship: "document:somedoc#viewer@user:tom" }
  ],
  OptionalTransactionMetadata: {
    "request_id": "12345"
  }
}
 

This allows callers to correlate write operations and the updates that come from the Watch API.

© 2024 AuthZed.