SignalK / signalk-server

An implementation of a Signal K central server for boats.
http://signalk.org
Apache License 2.0
308 stars 153 forks source link

feat: Server State Manager #519

Open webmasterkai opened 6 years ago

webmasterkai commented 6 years ago

I'd like to see a consolidated state manager for the server. Eventually used by all server components.

Start with Plugin state

I think the easiest place to start is related to server plugins. Currently app includes some methods for plugins to use that could be used by the server to capture and save plugin state.

These could be expanded to enable plugins to be completely stateless functions that utilized server state exclusively for getting and setting state.

It would enable plugins to define what events, ports, sockets they are listening on or emitting on. In this way other plugins and the server will know what is in use.

For each of these I was thinking it would be nice to have a human friendly name or description explaining what the plugin is emitting and what format (0183, N2K, SK, String, Buffer) it is in.

For example aisreporter could do something like:

app.registerEmit({
  id: 'selfAis',
  name: 'Self Vessel AIS Messages',
  format: 'NMEA0183',
})
// ...
app.emit('selfAis', message)

It would enable a dependency relationship between plugins. Now another plugin (net-relay) that handles emitting over UDP can provide a list of events that are being emitted to the user in the Admin UI. User can select selfAis and see that it is Self Vessel AIS Messages in NMEA0183 format. They then can assign a UDP hostname and port to emit those events to.

The net-relay plugin could do something like:

app.registerSocket({
  id: 'udp:192.168.4.10:2000',
  port: {randomlyAssigned}, // UDP must listens on a port even if only sending.
  name: 'Sending server events over UDP.',
  protocol: 'UDP',
})
app.on({
  eventId: 'selfAis',
  name: 'Sending via UDP to ${hostname}:${port}',
  listener, // listener function.
})

Now on the aisreporter UI we can show that there is a plugin net-relay listening to the selfAis event and what is doing with it. Plugin dependency can now show user warning before disabling aisreporter.

More Plugin Instance State

A plugin might have more than one "instance". Perhaps it has attached itself to more than one socket.

Proposal

I'd like to use Redux to store JSON serializable data and a custom data store that keeps references to functions and classes.

Potentially related to #466, #449, #422, #412, #409, #408.

webmasterkai commented 6 years ago

Having it be global state to the server would allow setting values for things like the port(s) that the HTTP server is using so the net-relay plugin doesn't try to bind itself to a port that is already in use. This will also allow the plugin to update its schema to prevent values that are invalid.

webmasterkai commented 6 years ago

Found some server app state stuff in /lib/config/config.js. I might take a stab at collecting the various process.env and path creating functions and make a single object that can be used for debugging. I'd love have a single API endpoint that could be used by users to copy and paste full configuration and options into issues. It'd also be helpful to have a listing of values available in the admin UI. Making it clear the paths where settings, defaults, plugin-config-data and the multiplexed logs are all saved would be helpful.

tkurki commented 6 years ago

Consider including a way to download everything as a zip file.

webmasterkai commented 6 years ago

Or uploading to the cloud somewhere

tkurki commented 6 years ago

Not all installations have connectivity, download & send would be more universal.

webmasterkai commented 6 years ago

There is probably an express thing to gzip static responses. I know there is state persistence handlers for Redux. Save to file on server and then provide download link. Is server compression of file transfer sufficient?

tkurki commented 6 years ago

I am not after compression, but a single file instead of multiple.