Cookoo's Synchronized Context

Jun 7 2014

Last week Masterminds released Cookoo 1.1.0. While most of the release is composed of minor bug fixes, we also added synchronization support to the cookoo.Context object.

In the past, we've resisted the synchronization of the context on two grounds: (1) Since context is not designed to be shared across requests, each request should work with only a copy of the context, and (2) once we hand things off to the request, it is the request's job to handle synchronization of its resources. And overall we've maintained this view on grounds that this is the most performance-conscious way of doing things.

But any good Go framework will respect Go's strong points. Over the course of developing real-world Cookoo apps, we came to realize that Cookoo was not making it easy for developers to leverage Go's concurrency. And the primary hinderance is the context. While you should be able to pass a context just about anywhere (it is, after all, one of the dependency injection mechanisms of Cookoo), passing a context to a go routine or sending it over a channel is a recipe for disaster.

And so with Cookoo 1.1 we have started to move away from the mentality that synchronization is the sole responsibility of the developer. While we are not requiring that a context be synchronized, we are now supplying a synchronization wrapper. You can use it like this:

import (
    "github.com/Masterminds/cookoo"
)

reg, router, plainContext := cookoo.Cookoo()

syncContext := SyncContext(plainContext)

This is generally a good idea when working with the cookoo/web package, though for simple web apps that never spawn their own goroutines, it may not be necessary.

Just be aware that the synchronizing a context does NOT automatically make all data stored inside of the context "thread-safe." That is, if you retrieve a value out of the context (or a datasource, for that matter), the context does not control access to that object once you have a handle to it. Two goroutines may each have a handle to the same data, and be able to mutate that data. It is still up to you to make sure this is done in a thread-safe way.