slct

command module
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2019 License: GPL-3.0 Imports: 38 Imported by: 0

README

slct

Demo API is available at http://51.158.121.7:8081/ Feel free to open issues in case you'll find a bug or have a nice idea :)

CSP

This service implements Go's CSP model over HTTP in persistent mode. It allows you to use select statement across multiple machines with same behavior and guarantees.

The main object of the API is state, which holds user-defined dump of a process state and a list of currently blocked selects. Each state can have multiple threads/coroutines/goroutines - for example if you have process that have 2 blocked goroutines - you will end up with 2 selects in state

The process definition & implementation is completely up to the user and not limited to Go or any other language. You can write business logic in JS without issues. Although writing in Go will allow you to leverage automatic state-machine generation

When all selects are blocking - the status of the state waiting - i.e. nothing happens. But when at least 1 select is resolved and unblocks - result is added to this select, and state status will be pending and your service is going to continue execution of this process/state.

There are 2 ways to resume process execution:

  • If callback is set - it will automatically triggered whenever process needs to be resumed. Callback will update state and return it in HTTP response back to service to save it.
  • If callback is not set - you have to poll the pending states, update them and manually save them with PUT /state/{id} request.

Caveats:

  • You have to process and put back the message within X seconds. Like with a normal message queue.
  • When state is processed - all selects that had result must be deleted. Selects that did not had result must not be deleted.

API

To start the process - we create state with initial result that contains the process initial select(s).

PUT /state/1
{
    "Data": "... initial process state...",
    "Selects": [{...}],
    "Callback": {
        Type: 1,
        URI: "http://.../callback"
    }
}
  • If you wish to start the process immediately - you can use default select statement to achieve that.
  • You can omit Callback if you are planning to poll this service
  • You can just omit the Data if you want to execute only select statement.
  • State creation operation can succeed only once, if the state was already created - you will receive lock error.
Callback

To support callback variant of resuming the process - add Callback to your state. When state will be ready to be resumed - the callback will be called with the state and expect updated state returned back:

{
    "Selects": [{
        ID: "1",
		"Cases": [{
			"Op": 1,
			"Chan": "chan1 id"
		},{
			"Op": 3,
			"Chan": "15600421234"
		},{
			"Op": 2,
			"Chan": "chan2 id"
            "Data": "hello world"
		}]
	}],
    "Data": "... updated process state ...",
    "Results": [{...}],
    "Callback": {
        Type: 1,
        URI: "http://.../callback"
    },
}
Polling

To support polling resume variant - omit callback from state, poll pending states periodically, process them and put them back using PUT /state/{id} within X seconds

Polling request looks like this: GET /state/poll?prefix=state_id_prefix&wait=30

prefix is a simple filter to poll only a subset of all pending. wait parameter can be used to do long-polling and block the state until some results are present.

Poll response:

[{
    "Selects": [{
        ID: "1",
		"Cases": [{
			"Op": 1,
			"Chan": "chan1 id"
		},{
			"Op": 3,
			"Chan": "15600421234"
		},{
			"Op": 2,
			"Chan": "chan2 id"
            "Data": "hello world"
		}]
	}],
    "Data": "... updated process state ...",
    "Results": [{...}],
    "Callback": {
        Type: 1,
        URI: "http://.../callback"
    },
}]

Installation

The service uses Raft protocol to linearize all select operations. This allows us to build exactly the same CSP model that is present in Go, but in highly-available manner. This means you have to run 3 select nodes with > 2GB RAM to make it work reliably 24/7. This also means that all of the nodes should have NTP setup correctly, as the system time for time channels is taken from the Raft leader, which can be any node.

Limits:

  • On a typical SSD server 3 node cluster with 10KB payloads you'll get ~1000-5000 req/sec, which should be way enough for asyncronous tasks management.
  • Number of active(waiting) selects in your cluster is limited by SSD size
  • 1MB max state size (soft limit). The system is limited to 50100MB/s thoughput, so bigger states decrease req/sec and increases RAM usage.

Warning

This is not production ready. Use at your own risk.

TODO

  • Get feedback
  • Integrate with async lib
  • Lock + Results easier concurrency handling

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL