Abstract
I'm working on a REST interface to a graph database (Titan/Gremlin-Server, but this shouldn't matter) that has a strong sense of type for vertices and edges. I'd like to design a REST API to perform CRUD operations while enforcing some type information.
Overview
The purpose of this database is to model the flow of information (a unit of which is called a message) across various actors, keeping track of the channels that mediate message routing. For instance, it can be said that a YouTuber (type: actor) produces a Video (type: message) and distributes it via a YouTube Channel (type: channel), to which another YouTuber (type: actor) is subscribed.
The data model is as follows with vertices represented as boxes and edges represented as arrows:
publish
|***************| ---------------------------------> |*******************|
| | | |
| | produce |*********| distribute | |
| Actor | ---------> | | ----------> | Channel |
| | | Message | | |
| | <--------- | | <---------- | |
| | notify |*********| deliver | |
| | | |
|***************| <--------------------------------- |*******************|
subscribe
To help with understanding, it is said that:
- An actor publishes to a channel
- An actor produces a message
- A message notifies an actor (inversely stated: an actor is notified of a message)
- A message is distributed via a channel
- A channel delivers a message (inversely stated: a message is delivered by a channel)
- An channel subscribes an actor (inversely stated: an actor is subscribed to a channel)
Notice how the types of the vertices in any edge-creation operation, createE(v1, v2), determines the type of edge that is created. For instance, an edge from an Actor to a Message is necessarily a produce edge. Likewise, an edge from Channel to Actor is necessarily a subscribe edge.
N.B.: Vertices in this model constitute (I think...) a mathematical category. We can think of edges as functions that map one category to another. For example, the function that takes us from an
Actorto aChannelis calledpublish, and is equivalent todistribute ∘ produce. I mention this because I had these principles in mind when designing the data model ... perhaps they can be leveraged for a REST API?
Problem Statement
Given the above data model, I need to create a REST API that supports basic CRUD operations for both vertices and edges. At a minimum, the API should:
- Operate on both individual resources and collections
- Provide a mechanism for constraining the vertices/edges on which a given API call operates (an informal and non-exhaustive example: "I want to create an edge going from the vertex with UUID
5F1506A2-4824-416D-95F2-BC2D82B15A29to all vertices created in the last hour) - Infer the type of edge to be created based on the source and destination vertex types, with the intent of validating user-supplied data (i.e.:
createE(some_actor, some_message)should implicitly create aproduce-type edge).
Current approach
One of the nicer properties of this data model is that edge type is fully-determined by the vertices at each end, and inversely, a pair of vertices can be typed based on an edge's type and direction. This makes it possible to do things like:
POST /:srcV/:dstV
{ edge JSON data goes here }
In doing so, we can validate the contents of the edge JSON data, ensuring that it corresponds to the type of edge implicitly created. For clarity, :srcV and :dstV are variables that will contain AGENT, MESSAGE or CHANNEL.
However, a few things are missing:
- how do I represent constraints
- how should constraints be transmitted over HTTP (query params?)
- how do I distinguish between resources and collections of resources?
Question 2 is of particular relevance because I want to be able to DELETE a collection of resources based on constraints. For instance, "remove all edges of type publish for which the actor is subscribed to a given channel".
This is my first time doing non-trivial work with REST, and it feels like I'm shoehorning this data-model into something that might not necessarily fit. Therefore, my question is twofold:
- Can someone point me in the right direction? Any ideas on what this API should look like?
- Any comments, suggestions or criticisms?
My understanding is that softwareengineering.stackexchange is for doing "whiteboarding" of sorts, so I hope the community will forgive the open-ended nature of this question. If it needs to be narrowed down, please guide me with questions and I'll update accordingly.
Many thanks in advance!
Additional notes
It's possible (perhaps even likely) that my vertex/edge nomenclature leads to confusion. I'm open to suggestions.
Some of my assumptions (particularly with respect to category theory) may be misguided or flat-out wrong. Corrections and friendly inquisitions are welcome!