func TestDingoAmqpMultiAppSuite(t *testing.T) { suite.Run(t, &amqpMultiAppTestSuite{ DingoMultiAppTestSuite{ CountOfCallers: 3, CountOfWorkers: 3, GenCaller: func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) if err != nil { return } brk, err := dgamqp.NewBroker(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.Producer) if err != nil { return } bkd, err := dgamqp.NewBackend(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Store) if err != nil { return } return }, GenWorker: func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) if err != nil { return } brk, err := dgamqp.NewBroker(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.NamedConsumer) if err != nil { return } bkd, err := dgamqp.NewBackend(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Reporter) if err != nil { return } return }, }, }) }
func TestDingoAmqpSingleAppSuite(t *testing.T) { suite.Run(t, &amqpSingleAppTestSuite{ DingoSingleAppTestSuite{ GenApp: func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) if err != nil { return } brk, err := dgamqp.NewBroker(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.Default) if err != nil { return } bkd, err := dgamqp.NewBackend(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Default) if err != nil { return } return }, }, }) }
func (me *localSingleAppTestSuite) SetupTest() { // reset the 'virtual wire' for every test me.wireBroker, me.wireBackend = make(chan []byte, 10), make(chan *dingo.ReportEnvelope, 10) me.GenApp = func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) if err != nil { return } brk, err := dingo.NewLocalBroker(dingo.DefaultConfig(), me.wireBroker) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.Default) if err != nil { return } bkd, err := dingo.NewLocalBackend(dingo.DefaultConfig(), me.wireBackend) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Default) if err != nil { return } return } me.DingoSingleAppTestSuite.SetupTest() }
func ExampleApp_local() { // this example demonstrates a job queue runs in background var err error defer func() { if err != nil { fmt.Printf("%v\n", err) } }() // a App in local mode app, err := dingo.NewApp("local", nil) if err != nil { return } // register a worker function murmur err = app.Register("murmur", func(msg string, repeat int, interval time.Duration) { for ; repeat > 0; repeat-- { select { case <-time.After(interval): fmt.Printf("%v\n", msg) } } }) if err != nil { return } // allocate 5 workers, sharing 1 report channel _, err = app.Allocate("murmur", 5, 1) if err != nil { return } results := []*dingo.Result{} // invoke 10 tasks for i := 0; i < 10; i++ { results = append( results, dingo.NewResult( // name, option, parameter#1, parameter#2, parameter#3... app.Call("murmur", nil, fmt.Sprintf("this is %d speaking", i), 10, 100*time.Millisecond), )) } // wait until those tasks are done for _, v := range results { err = v.Wait(0) if err != nil { return } } // release resource err = app.Close() if err != nil { return } }
func TestDingoLocalModeTestSuite(t *testing.T) { suite.Run(t, &localModeTestSuite{ DingoSingleAppTestSuite{ GenApp: func() (*dingo.App, error) { return dingo.NewApp("local", nil) }, }, }) }
func TestDingoEventFromBackendAndBroker(t *testing.T) { // make sure events from backend/broker are published ass := assert.New(t) app, err := dingo.NewApp("remote", nil) ass.Nil(err) if err != nil { return } // prepare a caller _, _, err = app.Use(&testFakeProducer{make(chan *dingo.Event, 10)}, dingo.ObjT.Producer) ass.Nil(err) if err != nil { return } _, _, err = app.Use(&testFakeStore{make(chan *dingo.Event, 10)}, dingo.ObjT.Store) ass.Nil(err) if err != nil { return } // register a task err = app.Register("TestDingoEvent", func() {}) ass.Nil(err) if err != nil { return } // there should be 2 events _, events, err := app.Listen(dingo.ObjT.All, dingo.EventLvl.Info, 0) ass.Nil(err) if err != nil { return } // send a task _, err = app.Call("TestDingoEvent", nil) ass.Nil(err) if err != nil { return } // exactly two event should be received. e1 := <-events e2 := <-events ass.True(e1.Origin|e2.Origin == dingo.ObjT.Producer|dingo.ObjT.Store) ass.True(e1.Level == dingo.EventLvl.Info) ass.True(e2.Level == dingo.EventLvl.Info) ass.True(e1.Payload.(string) == "Send" || e2.Payload.(string) == "Send") ass.True(e1.Payload.(string) == "Poll" || e2.Payload.(string) == "Poll") // release resource ass.Nil(app.Close()) }
func TestDingoUse(t *testing.T) { var ( err error ass = assert.New(t) ) defer func() { ass.Nil(err) }() app, err := dingo.NewApp("remote", nil) if err != nil { return } defer func() { ass.Nil(app.Close()) }() // new a fake object, whose event channel is accessible obj := &testFakeObject{} chk := func(id int, used int, err error) { ass.Equal(0, used) ass.NotNil(err) } // attach it with different types chk(app.Use(obj, dingo.ObjT.Producer)) chk(app.Use(obj, dingo.ObjT.Consumer)) chk(app.Use(obj, dingo.ObjT.NamedConsumer)) chk(app.Use(obj, dingo.ObjT.Reporter)) chk(app.Use(obj, dingo.ObjT.Store)) err = app.Register("TestDingoUse", func() {}) if err != nil { return } remain, err2 := app.Allocate("TestDingoUse", 10, 1) ass.Equal(10, remain) ass.NotNil(err2) reports, err2 := app.Call("TestDingoUse", nil) ass.Nil(reports) ass.NotNil(err2) }
func BenchmarkLocal(b *testing.B) { var ( err error count = 1 msg = "test string" ) defer func() { if err != nil { b.Fatalf("failed: %v\n", err) } }() app, err := dingo.NewApp("local", nil) if err != nil { return } err = app.Register("myWork", testWork) if err != nil { return } _, err = app.Allocate("myWork", 10, 3) if err != nil { return } // setup for invoker err = app.AddMarshaller(101, &struct { dingo.GobMarshaller testMyInvoker }{ dingo.GobMarshaller{}, testMyInvoker{}, }) if err != nil { return } err = app.SetMarshaller("myWork", 101, 101) if err != nil { return } // setup for idmaker err = app.AddIDMaker(101, &dingo.SeqIDMaker{}) if err != nil { return } err = app.SetIDMaker("myWork", 101) if err != nil { return } // reset timer for preparation b.ResetTimer() var result *dingo.Result b.RunParallel(func(pb *testing.PB) { for pb.Next() { result = dingo.NewResult(app.Call("myWork", nil, count, msg)) result.Wait(0) } }) }
func TestDingoEventOrigin(t *testing.T) { var ( err error ass = assert.New(t) ) defer func() { ass.Nil(err) }() app, err := dingo.NewApp("remote", nil) if err != nil { return } defer func() { ass.Nil(app.Close()) }() // new a fake object, whose event channel is accessible obj := &testFakeObject{events: make(chan *dingo.Event, 1)} _, _, err = app.Use(obj, 0) if err != nil { return } chk := func(ch <-chan *dingo.Event, origin int) { e := <-ch ass.Equal(origin, e.Origin) } // subscribe bridge event idBridge, chBridge, err := app.Listen(dingo.ObjT.Bridge, dingo.EventLvl.Debug, 0) if err != nil { return } // subscribe all event idAll, chAll, err := app.Listen(dingo.ObjT.All, dingo.EventLvl.Debug, 0) if err != nil { return } // send a mapper event obj.events <- dingo.NewEvent(dingo.ObjT.Mapper, dingo.EventLvl.Error, 0, "mapper") chk(chAll, dingo.ObjT.Mapper) // send a bridge event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge, dingo.EventLvl.Error, 0, "bridge") chk(chAll, dingo.ObjT.Bridge) chk(chBridge, dingo.ObjT.Bridge) // send a mapper | bridge event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge|dingo.ObjT.Mapper, dingo.EventLvl.Error, 0, "bridge") chk(chAll, dingo.ObjT.Bridge|dingo.ObjT.Mapper) chk(chBridge, dingo.ObjT.Bridge|dingo.ObjT.Mapper) err = app.StopListen(idBridge) if err != nil { return } err = app.StopListen(idAll) if err != nil { return } }
func TestDingoEventLevel(t *testing.T) { var ( err error ass = assert.New(t) ) defer func() { ass.Nil(err) }() // attach a fake object app, err := dingo.NewApp("local", nil) if err != nil { return } defer func() { ass.Nil(app.Close()) }() // allocate channels slice chs := make([]<-chan *dingo.Event, 4) Debug, Info, Warning, Error := 0, 1, 2, 3 idDebug, idInfo, idWarning, idError := 0, 1, 2, 3 recv := func(which, lvl int) { e := <-chs[which] ass.Equal(lvl, e.Level) } // new a fake object, whose event channel is accessible obj := &testFakeObject{events: make(chan *dingo.Event, 1)} _, _, err = app.Use(obj, 0) if err != nil { return } // subscribe a Debug channel idDebug, chs[Debug], err = app.Listen(dingo.ObjT.All, dingo.EventLvl.Debug, 0) if err != nil { return } // subscribe an Info channel idInfo, chs[Info], err = app.Listen(dingo.ObjT.All, dingo.EventLvl.Info, 0) if err != nil { return } // subscribe a Warning channel idWarning, chs[Warning], err = app.Listen(dingo.ObjT.All, dingo.EventLvl.Warning, 0) if err != nil { return } // subscribe an Error channel idError, chs[Error], err = app.Listen(dingo.ObjT.All, dingo.EventLvl.Error, 0) if err != nil { return } // send an error event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge, dingo.EventLvl.Error, 0, "error") recv(Error, dingo.EventLvl.Error) recv(Warning, dingo.EventLvl.Error) recv(Info, dingo.EventLvl.Error) recv(Debug, dingo.EventLvl.Error) // send a warning event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge, dingo.EventLvl.Warning, 0, "warning") recv(Warning, dingo.EventLvl.Warning) recv(Info, dingo.EventLvl.Warning) recv(Debug, dingo.EventLvl.Warning) // send an info event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge, dingo.EventLvl.Info, 0, "info") recv(Info, dingo.EventLvl.Info) recv(Debug, dingo.EventLvl.Info) // send a debug event obj.events <- dingo.NewEvent(dingo.ObjT.Bridge, dingo.EventLvl.Debug, 0, "debug") recv(Debug, dingo.EventLvl.Debug) // stop debug channel, and send an debug event err = app.StopListen(idDebug) if err != nil { return } // stop info channel, and send an info event err = app.StopListen(idInfo) if err != nil { return } // stop warning channel, and send an warning event err = app.StopListen(idWarning) if err != nil { return } // stop error channel, and send an error event err = app.StopListen(idError) if err != nil { return } }
func (me *localMultiAppTestSuite) SetupTest() { // reset the 'virtual wire' for every test me.wireBroker, me.wireBackend = make(chan []byte, 10), make(chan *dingo.ReportEnvelope, 10) me.GenCaller = func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) me.Nil(err) if err != nil { return } brk, err := dingo.NewLocalBroker(dingo.DefaultConfig(), me.wireBroker) me.Nil(err) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.Producer) me.Nil(err) if err != nil { return } bkd, err := dingo.NewLocalBackend(dingo.DefaultConfig(), me.wireBackend) me.Nil(err) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Store) me.Nil(err) if err != nil { return } return } me.GenWorker = func() (app *dingo.App, err error) { app, err = dingo.NewApp("remote", nil) me.Nil(err) if err != nil { return } brk, err := dingo.NewLocalBroker(dingo.DefaultConfig(), me.wireBroker) me.Nil(err) if err != nil { return } _, _, err = app.Use(brk, dingo.ObjT.Consumer) me.Nil(err) if err != nil { return } bkd, err := dingo.NewLocalBackend(dingo.DefaultConfig(), me.wireBackend) me.Nil(err) if err != nil { return } _, _, err = app.Use(bkd, dingo.ObjT.Reporter) me.Nil(err) if err != nil { return } return } me.DingoMultiAppTestSuite.SetupTest() }
func ExampleApp_Use_caller() { /* import ( "fmt" "time" "github.com/mission-liao/dingo" "github.com/mission-liao/dingo/amqp" ) */ // this example demostrate a caller based on AMQP, used along with ExampleApp_Use_worker // make sure you install a rabbitmq server locally. var err error defer func() { if err != nil { fmt.Printf("%v\n", err) } }() // an App in remote mode app, err := dingo.NewApp("remote", nil) if err != nil { return } // attach an AMQP producer to publish your tasks broker, err := dgamqp.NewBroker(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(broker, dingo.ObjT.Producer) if err != nil { return } // attach an AMQP store to receive reports from datastores. backend, err := dgamqp.NewBackend(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(backend, dingo.ObjT.Store) if err != nil { return } // register a work function that murmur err = app.Register("murmur", func(speech *struct { Prologue string Script []string }, interval time.Duration) (countOfSentence int) { // speak the prologue fmt.Printf("%v:\n", speech.Prologue) countOfSentence++ // speak the script for _, v := range speech.Script { <-time.After(interval) fmt.Printf("%v\n", v) countOfSentence++ } // return the total sentence we talked return }) if err != nil { return } // compose a script to talk script := &struct { Prologue string Script []string }{ Script: []string{ "Today, I'm announcing this library.", "It should be easy to use, ", "and fun to play with.", "Merry X'mas.", }, } // invoke 20 tasks results := []*dingo.Result{} for i := 0; i < 20; i++ { script.Prologue = fmt.Sprintf("this is %d speaking", i) results = append(results, dingo.NewResult( // name, option, parameter#1, parameter#2 ... app.Call("murmur", nil, script, 100*time.Millisecond), )) } // wait until those tasks are done for _, v := range results { err = v.Wait(0) if err != nil { return } // result is accessible fmt.Printf("one worker spoke %v sentences\n", v.Last.Return()[0].(int)) } // release resource err = app.Close() if err != nil { return } }
func ExampleCustomMarshaller() { /* import ( "encoding/json" "fmt" "github.com/mission-liao/dingo" ) */ // this example demonstrate the usage of using a // customized marshaller by encoding every parameter // in JSON. // And invoke it with customized invoker var err error defer func() { if err != nil { fmt.Printf("%v\n", err) } }() // an App in remote mode, with local backend/broker app, err := dingo.NewApp("remote", nil) if err != nil { return } // attach a local broker. broker, err := dingo.NewLocalBroker(dingo.DefaultConfig(), nil) if err != nil { return } _, _, err = app.Use(broker, dingo.ObjT.Default) // attach a local backend backend, err := dingo.NewLocalBackend(dingo.DefaultConfig(), nil) if err != nil { return } _, _, err = app.Use(backend, dingo.ObjT.Default) if err != nil { return } // register customize marshaller & invoker err = app.AddMarshaller(101, &struct { testMyInvoker3 dingo.CustomMarshaller }{ testMyInvoker3{}, dingo.CustomMarshaller{Codec: &testCustomMarshallerCodec{}}, }) if err != nil { return } // register worker function err = app.Register("concat", func(words []string) (ret string) { for _, v := range words { ret = ret + v } return }) if err != nil { return } // change marshaller of worker function err = app.SetMarshaller("concat", 101, 101) if err != nil { return } // allocate workers _, err = app.Allocate("concat", 1, 1) if err != nil { return } // trigger the fire... result := dingo.NewResult(app.Call("concat", nil, []string{"Merry ", "X", "'mas"})) err = result.Wait(0) if err != nil { return } result.OnOK(func(ret string) { fmt.Printf("%v\n", ret) }) err = app.Close() if err != nil { return } }
func ExampleApp_Use_worker() { /* import ( "fmt" "os" "time" "github.com/mission-liao/dingo" "github.com/mission-liao/dingo/amqp" ) */ // this example demonstrate a worker based on AMQP, used along with ExampleApp_Use_caller // make sure you install a rabbitmq server locally. var err error defer func() { if err != nil { fmt.Printf("%v\n", err) } }() // an App in remote mode app, err := dingo.NewApp("remote", nil) if err != nil { return } // attach an AMQP consumer to receive tasks broker, err := dgamqp.NewBroker(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(broker, dingo.ObjT.NamedConsumer) if err != nil { return } // attach an AMQP reporter to publish reports backend, err := dgamqp.NewBackend(dgamqp.DefaultAmqpConfig()) if err != nil { return } _, _, err = app.Use(backend, dingo.ObjT.Reporter) if err != nil { return } // register a work function that murmur err = app.Register("murmur", func(speech *struct { Prologue string Script []string }, interval time.Duration) (countOfSentence int) { // speak the prologue fmt.Printf("%v:\n", speech.Prologue) countOfSentence++ // speak the script for _, v := range speech.Script { <-time.After(interval) fmt.Printf("%v\n", v) countOfSentence++ } // return the total sentence we talked return }) if err != nil { return } // allocate 1 workers, sharing 1 report channel _, err = app.Allocate("murmur", 1, 1) if err != nil { return } // wait until a key stroke var stroke []byte = make([]byte, 100) fmt.Println("waiting for tasks...stop waiting by pressing enter") os.Stdin.Read(stroke) // release resource err = app.Close() if err != nil { return } }