Skip to content

How do Graph Store, Board Server, and versioning fit together?

Dimitri Glazkov edited this page Dec 14, 2024 · 11 revisions

Graph Store

The graph store knows all graphs. It manages graph mutations and sends events whenever graphs are changed, etc. The graph store is the abstraction that enables lazy updates to currenPorts in InspectableGraph: because we can rely on GraphStore's "update" event, we can just re-read the currentPorts whenever an update comes through.

  • There are mutable and immutable graphs
  • The mutable graph (represented by a MutableGraph instance) is a graph whose topology changes.
  • The immutable graph is a graph snapshot -- it is frozen in time and can't be changed anymore.
  • The InspectableGraph instances backed by MutableGraph are great for editing use cases.
  • The InspectableGraph instances backed by immutable graph are great for capturing runs.

Two kinds of versioning

  • Graph Store versioning - in-memory, immediate, used for undo/redo (ideally) and for getting updates from the graph store

  • Board Server versioning - persistent, used to version published boards

Graph Store Versioning

Graph store needs to somehow store versions of graphs. For now, let's use plain Date timestamps to capture versions. We may go with something more sophisticated later.

Each graph in graph store has a unique ID, which is a UUID that is generated at the time of adding the graph to the store.

So, the graph store item is a MutableGraph with a list of timestamp-keyed snapshots that are its previous versions. The list is sorted by timestamp, most recent first.

To access a timestamped version, we'll need an API that gets a snapshot:

export type MutableGraphStore = TypedEventTargetType<GraphsStoreEventMap> & {
  // ...

  inspectSnapshot(
    id: MainGraphIdentifier,
    graphId: GraphIdentifier,
    timestamp?: number, // the timestamp
  ): InspectableGraph | undefined;
};

...

// Returns the first available snapshot
const snapshot = store.inspectSnapshot(id, graphId, 0);

...

// Returns the last available snapshot
const snapshot = store.inspectSnapshot(id, graphId);

...

// Returns the first snapshot that was captured
// at `timestamp` or the first snapshot captured after `timestamp`.
const snapshot = store.inspectSnapshot(id, graphId, timestamp);

So, the snapshot API doesn't really create snapshots. It just retrieves them.

However, in the beginning, we can get away with only supporting the "last available snapshot", because that is all we need for correctly observing runs.

Eventually, we may have a whole set of APIs to explore snapshots, but we don't need it yet.

Board Server

Board Servers serve boards, and in that regard, they are spiritually similar to Graph Store. Except they are remote. So maybe one way to position the GraphProvider interface is as an API to a remote Graph Store.

One thing's for sure: we need to make Graph Store be aware of the GraphProvider interface, supplying them as constructor args, similar to Loader. Maybe Graph Store is the loader now.

  • The board list from a board server can be interpreted as a list of first snapshots of boards, and they can be loaded whenever. However, in this case, we don't actually want the initial to kick of the load, because this will cause all the boards to be loaded. So, it sounds like "refresh on initial" might need to be configurable?

Board Server Versioning

The board server API needs to have the ability to return:

  • latest version -- equivalent to tip-of-trunk: it is always updated, reflects every save.
  • specific version -- a snapshot at a particular time, tagged with a version number
  • current published -- a pointer to a specific version

URLs:

  • latest: https://board.server/boards/@user/board.bgl.json@latest
  • specific: https://board.server/boards/@user/board.bgl.json@1.0.3
  • published: https://board.server/boards/@user/board.bgl.json

UX:

  • see a list of versions
  • create a new version
  • get URL of specific version
  • mark version as currently published

Brainstorming

This unique id is matched to graph URL, so maybe in the future we will just use the graph URL.

For graphs that don't have URLs (pasted in, for example), we'll create a Blob URL maybe?