import "github.com/owulveryck/cortical"
Cortical is a go framework middleware piece of code that acts as a message dispatcher. The messages are transmitted in full duplex over a websocket.
Cortical is therefore a very convenient way to distribute messages to "processing units" (other go functions) and to get the responses back in a concurrent and asynchronous way.
The "processing units" are called Cortexes and do not need to be aware of any web mechanism.
Actually I have developed this code as a support for my tests with tensorflow, Google Cloud Plafeform and AWS ML services. I needed a way to capture images from my webcam. I have used my chrome browser for this purpose. Every Cortex is a specific ML implementation (eg a Memory Cortex that captures all the images and send them to a cloud storage is needed for training models).
See my blog post "Chrome, the eye of the cloud - Computer vision with deep learning and only 2Gb of RAM" for more explanation.
A cortex is any go code that provides two functions:
- A "send" function that returns a channel of
[]byte
. The content of the channel is sent to the websocket once available (cfGetInfoFromCortexFunc
) - A "receive" method that take a pointer of
[]byte
. This function is called each time a message is received (cfSendInfoToCortex
)
A cortex object must therefore be compatible with the cortical.Cortex
interface:
ex:
// echo is a dummy type that reads a message, and send back an "ack"
type echo struct{}
func new() *echo {
return &echo{}
}
// NewCortex is filling the cortical.Cortex interface
func (e *echo) NewCortex(ctx context.Context) (cortical.GetInfoFromCortexFunc, cortical.SendInfoToCortex) {
c := make(chan []byte)
return func(ctx context.Context) chan []byte {
return c
}, func(ctx context.Context, b *[]byte) {
c <- *b
}
}
Cortical take care of extracting and sending the []byte
to the websocket and dispatches them through all the cortexes.
Registering the cortexes and creating a http.HandlerFunc
By now, the registration of cortexes is done at the creation of the Cortical object.
WARNING This will probably change in the future
brain := &cortical.Cortical{
Upgrader: websocket.Upgrader{},
Cortexes: []cortical.Cortex{
&echo{}, // See example in the previous paragraph
},
}
http.HandleFunc("/ws", brain.ServeWS)
log.Fatal(http.ListenAndServe(":8080", nil))
See the example in godoc
- Because I love go
- Because I only know how to code in go
- The real reason: concurrency (take a look at Rob Pike - 'Concurrency Is Not Parallelism' on youtube to truly understand why)
The API may change a lot; use it at your own risks. PR are welcome.
- Tests
- Doc
- Benchmarks
- Demo
- More functional tests
- Using the context cancel mechanism instead of my
done chan
- Evaluating the opportunity of changing the interface for an
io.ReadWriteCloser
- More and better doc