feature(worker): context object to store runtime configurations

This commit is contained in:
bigeagle 2016-04-21 20:45:06 +08:00
parent f0a0552e50
commit f95a0f9a6f
No known key found for this signature in database
GPG Key ID: 9171A4571C27920A
3 changed files with 138 additions and 0 deletions

61
worker/context.go Normal file
View File

@ -0,0 +1,61 @@
package worker
// Context object aims to store runtime configurations
import "errors"
// A Context object is a layered key-value storage
// when enters a context, the changes to the storage would be stored
// in a new layer and when exits, the top layer poped and the storage
// returned to the state before entering this context
type Context struct {
parent *Context
store map[string]interface{}
}
// NewContext returns a new context object
func NewContext() *Context {
return &Context{
parent: nil,
store: make(map[string]interface{}),
}
}
// Enter generates a new layer of context
func (ctx *Context) Enter() *Context {
return &Context{
parent: ctx,
store: make(map[string]interface{}),
}
}
// Exit return the upper layer of context
func (ctx *Context) Exit() (*Context, error) {
if ctx.parent == nil {
return nil, errors.New("Cannot exit the bottom layer context")
}
return ctx.parent, nil
}
// Get returns the value corresponding to key, if it's
// not found in the current layer, return the lower layer
// context's value
func (ctx *Context) Get(key string) (interface{}, bool) {
if ctx.parent == nil {
if value, ok := ctx.store[key]; ok {
return value, true
}
return nil, false
}
if value, ok := ctx.store[key]; ok {
return value, true
}
return ctx.parent.Get(key)
}
// Set sets the value to the key at current layer
func (ctx *Context) Set(key string, value interface{}) {
ctx.store[key] = value
}

64
worker/context_test.go Normal file
View File

@ -0,0 +1,64 @@
package worker
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestContext(t *testing.T) {
Convey("Context should work", t, func() {
ctx := NewContext()
So(ctx, ShouldNotBeNil)
So(ctx.parent, ShouldBeNil)
ctx.Set("logdir1", "logdir_value_1")
ctx.Set("logdir2", "logdir_value_2")
logdir, ok := ctx.Get("logdir1")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "logdir_value_1")
Convey("When entering a new context", func() {
ctx = ctx.Enter()
logdir, ok = ctx.Get("logdir1")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "logdir_value_1")
ctx.Set("logdir1", "new_value_1")
logdir, ok = ctx.Get("logdir1")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "new_value_1")
logdir, ok = ctx.Get("logdir2")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "logdir_value_2")
Convey("When accesing invalid key", func() {
logdir, ok = ctx.Get("invalid_key")
So(ok, ShouldBeFalse)
So(logdir, ShouldBeNil)
})
Convey("When exiting the new context", func() {
ctx, err := ctx.Exit()
So(err, ShouldBeNil)
logdir, ok = ctx.Get("logdir1")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "logdir_value_1")
logdir, ok = ctx.Get("logdir2")
So(ok, ShouldBeTrue)
So(logdir, ShouldEqual, "logdir_value_2")
Convey("When exiting from top bottom context", func() {
ctx, err := ctx.Exit()
So(err, ShouldNotBeNil)
So(ctx, ShouldBeNil)
})
})
})
})
}

13
worker/provider.go Normal file
View File

@ -0,0 +1,13 @@
// mirror provider is the wrapper of mirror jobs
package worker
// a mirrorProvider instance
type mirrorProvider interface {
// run mirror job
Run()
// terminate mirror job
Terminate()
// get context
Context()
}