Flowcharts
Note
These pages address how to build a Fediverse application for an end user. There are other use cases, see this comment
This is mostly a sketch for the architecture of a Fediverse application. It should look something like this:
graph LR
A((Fediverse)) ==>|POST| B[bovine_herd]
B ==>|POST| A
B <--> BDB[(Actor DB)]
B --> T[bovine_timeline]
A ==>|GET objects| T
T --> B
T <--> TDB[(Timeline DB)]
B --> D[Device Gateway]
D --> T
D1[\Device One\] -.-> D
D -.-> D1
D2[\Device Two\] -.-> D
D -.-> D2
This diagram captures my thinking. It is unfortunately, useless as it does not explain how certain types of data flow. Furthermore, while the above diagram captures how I imagine the data flow, it does not capture the technical aspects.
I will try to illuminate these two aspects in the next sections. Horizontal graphs concerns itself with how data flows through the application. Vertical graphs discusses the more technical aspects.
Horizontal graphs
Horizontal means here how the data flows across the different components.
Incoming Activity
graph LR
A((Fediverse)) ==>|POST| B[bovine_herd]
B --> T[bovine_timeline]
T -->|?| TDB[(Timeline DB)]
B --> D[Device Gateway]
D -.-> D1[\Device One\]
D -.-> D2[\Device Two\]
Where the ?
signifies that bovine_timeline only records this
activity, if it interacts with one's own content.
For things managed by bovine_herd such as followers, one would arrive at
graph LR
A((Fediverse)) ==>|POST| B[bovine_herd]
B --> BDB[(Actor DB)]
B --> D[Device Gateway]
D -.-> D1[\Device One\]
D -.-> D2[\Device Two\]
Outgoing Activity
graph LR
D1[\Device One\] -.-> D[Device Gateway]
D -.-> D2[\Device Two\]
D --> T[bovine_timeline]
T --> TDB[(Timeline DB)]
T --> B[bovine_herd]
B ==>|POST| A((Fediverse))
We note that this diagram forks differently than the incoming one. This is due to bovine_timeline being in charge of storing activities. We furthermore note that the Device Gateway is responsible for ensuring that the devices stay synchronized.
Having a service explicit in charge of storing an user's data, makes giving the user all their data trivial: Just hand them a database dump.
Lookup from the Fediverse
For an object
graph LR
A((Fediverse)) ==>|GET objects| T[bovine_timeline]
T <--> TDB[(Timeline DB)]
For an actor
graph LR
A((Fediverse)) ==>|GET| B[bovine_herd]
B <--> BDB[(Actor DB)]
Lookup to the Fediverse
graph LR
D1[\Device One\] -.-> D[Device Gateway]
D --> B[bovine_herd]
B --> T[bovine_timeline]
B ==>|GET| A((Fediverse))
One wants to insert some caching here. See bovine Issue #59.
From the internet
graph LR
I((intenret)) ==>|GET objects| T[bovine_timeline]
T <--> TDB[(Timeline DB)]
Vertical Graphs
These vertical graphs are meant to give a technical impression of how things work.
bovine_herd
The main task of bovine_herd is to be the point of interaction between authenticated requests from the Fediverse and our Fediverse application. Authentication is handled by cattle_grid.
graph TD
F((Fediverse)) ==>|GET+POST| BS
F <==>|GET+POST| BP
BS[Server] -->|publish| R[RabbitMQ]
BP[Processor] -->|publish+subscribe| R
BP -.->|r+w| BDB[(Actor DB)]
BS -.->|read| BDB
BP -.->|r+w| BC[(Cache)]
R --> RA{{Rest of the Application}}
- This architecture has the advantage that the server only needs read access to the database
- The processor will be in charge of performing requests to the Fediverse. This is both POST for sending activities, as GET to lookup stuff, see fetch_object. The purpose of Cache is to cache these requests.
- The server will probably only manage a few objects associated with the actor, as the actor profile and the following/followers collection. So other parts of the Fediverse application will also answer to GET requests from the Fediverse.
- The server should be able to manage an outbox/inbox as a collection of activity ids.
- Managing outbox, inbox, following, followers collection should be optional features.
- Should probably support auto accepting follow requests
Note
The arrow is only meant to go "bovine_herd processor" to Fediverse, but mermaid doesn't let me.
A note on other parts
All parts after bovine_herd are specific to the use case of a human user. For example something like an RSS to ActivityPub bridge would look something like
graph TD
C[Cron] -->|execute| R[RSS fetcher]
R ==>|GET| W((feed.rss))
R -->|publish| RMQ[RabbitMQ]
with maybe a config file and a log of already published entries.