legato-old icon indicating copy to clipboard operation
legato-old copied to clipboard

Postbox implementation

Open bluskript opened this issue 3 years ago • 2 comments

This is necessary for lossless intercom between servers. Necessary for the guild list and DMs.

bluskript avatar Dec 28 '20 01:12 bluskript

Problem

Currently, there is no way to receive data between two hosts. In addition, the guild list is currently implemented in a way that is prone to error, as it requires clients to manually invoke RemoveGuildFromGuildList after the client leaves a guild. Having a way to send messages between hosts would allow the guild list to be automatically managed between hosts, and for DM invites to work across hosts.

Solution

Provide an endpoint to post an event to a host, and additionally have a way to 'pull in' events from a target host in case the host was down and unable to receive events. This ensures that there is no loss of events if a host goes down.

Implementation

When a host wants to send an event to another host, they will first try to call PostEvent on the remote host. PostEvent notifies a host of an event. If a PostEvent fails, the origin host will add the event to a queue of pending events.

When PostEvent is called, the host receiving the event needs to know what host it came from. The host sending the event must generate a random UUID of size 16, and sign it with its private key as a JWT. In the PostEvent, the token value will be set to the signed JWT, and the host value will be set to the hostname of the server.

The host receiving the PostEvent must send a auth.v1.GetKey() request to the host specified in the PostEvent to obtain the public key. If the public key successfully verifies the token specified in the request, then it is a valid request from that host.

When the public key is requested, it is cached and only invalidates if the cached public key does not verify a request correctly.

When a server starts, what it does first is check to see if any hosts it came in contact with has had any events using Sync. Sync will terminate when all events have been received on the stream.

When a host is receiving a Sync request, it has to perform the same authentication method which was described in PostEvent to know the correct host is requesting events.

Protobuf definition:

message SyncRequest {
  string token = 1;
  string host = 2;
}

message PostboxEvent { google.protobuf.Any event = 1; }

message PostEventRequest {
  SyncRequest sync_request = 1;
  PostBoxEvent event = 2;
}

service PostboxService {
  rpc Sync(SyncRequest) returns (stream PostboxEvent) {}
  rpc PostEvent(PostEventRequest) returns (google.protobuf.Empty) {}
}

bluskript avatar Mar 24 '21 21:03 bluskript

looks fine to me

pontaoski avatar Jun 05 '21 02:06 pontaoski