anagent

package module
v0.0.0-...-626d9ac Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2018 License: MIT Imports: 8 Imported by: 27

README

Anagent Build Status codecov Go Report Card godoc

Minimalistic, pluggable Golang evloop/timer handler with dependency-injection - based on codegangsta/inject - go-macaron/inject and chuckpreslar/emission.

Anagent is a lightweight library that allows you to plug inside to other event loops, or allows you to handle and create your own within your application - leaving the control to you.

It comes with dependency-injection from codegangsta/inject, and it's also a soft-wrapper to chuckpreslar/emission, adding to it dependency injection capabilities and timer handlers.

Usage

Event Emitter with Dependency injection
    package main

    import (
    	"log"
    	"github.com/mudler/anagent"
    )

    type TestTest struct {
    	Test string
    }

    func main() {
    	agent := anagent.New()
    	mytest := &TestTest{Test: "PONG!"}
    	agent.Map(mytest)

    	agent.Once("test", func(te *TestTest, l *log.Logger) {
    		if te.Test == "PONG!" {
    			l.Println("It just works!")
    		}
    	})

    	agent.Emit("test")
    }

What happened here? we mapped our structure instance (TestTest) inside the agent with (agent.Map()), and all fired events can access to them.

Timer / Reactor
    package main

    import "github.com/mudler/anagent"
    import "fmt"

    type TestTest struct {
            Test string
    }

    func main() {
            agent := anagent.New()
            mytest := &TestTest{Test: "PONG!"}
            agent.Map(mytest)

            agent.Emitter().On("test", func(s string) { fmt.Println("Received: " + s) })

            // Not recurring timer
            agent.TimerSeconds(int64(3), false, func(a *anagent.Anagent, te *TestTest) {
                    a.Emitter().Emit("test", te.Test)
                    go a.Stop()
            })

            agent.Start() // Loops here and never returns
    }

The code portion will start and wait for 3 seconds, then it will execute the callback (not recurring, that's why the false) that will fire a custom event defined before (note, it's not using the dependency-injection capabilities, thus it's accessing the emitter handler directly with agent.Emitter()).

The difference is that when we access to On() provided by agent.On(), we access to the agent dependencies, that have been mapped with agent.Map() - otherwise, with agent.Emitter().On() we are free to bind any arguments to the event callback.

After the event is fired, the timer stops the eventloop (a.Stop()), so the program returns.

Hook into other loops

It is often in other framework to use loop patterns, as example in framework for game development, network agents, and such. We can hook into other loops, and run the agent Step function, so we can still leverage the evloop functionalities.

    package main

    import "github.com/mudler/anagent"
    import "fmt"

    type TestTest struct {
    	Test string
    }

    func main() {
    	agent := anagent.New()
    	mytest := &TestTest{Test: "PONG!"}
    	agent.Map(mytest)

        // Reply with a delay of 2s
    	agent.Emitter().On("test", func(s string) {
    		agent.TimerSeconds(int64(2), false, func() {
    			fmt.Println("Received: " + s)
    		})
    	})

    	// Recurring timer
    	agent.TimerSeconds(int64(3), true, func(a *anagent.Anagent, te *TestTest) {
    		fmt.Println("PING!")
    		a.Emitter().Emit("test", te.Test)
    	})

    	for { // Infinite loop
    		agent.Step()
    	}
    }

Documentation

Index

Constants

View Source
const VERSION = "0.1"

VERSION contains the Anagent version number

Variables

This section is empty.

Functions

func GetMD5Hash

func GetMD5Hash(text string) string

GetMD5Hash is a utility function to get MD5 digest of the supplied string.

func RandTimer

func RandTimer(m map[TimerID]*Timer) (TimerID, *Timer)

Types

type Anagent

type Anagent struct {
	inject.Injector
	sync.Mutex

	// Fatal         bool
	Started       bool
	BusyLoop      bool
	StartedAccess *sync.Mutex
	// contains filtered or unexported fields
}

Anagent represents the top level application. inject.Injector methods can be invoked to map services on a global level.

func New

func New() *Anagent

New creates a bare bones Anagent instance. Use this method if you want to have full control over the middleware that is used.

func (*Anagent) AddRecurringTimerSeconds

func (a *Anagent) AddRecurringTimerSeconds(seconds int64, handler Handler) TimerID

AddRecurringTimerSeconds is used to set a recurring timer, that will fire after the seconds supplied. It requires seconds supplied as int64 and at the end the callback to be fired at the desired time.

func (*Anagent) AddTimerSeconds

func (a *Anagent) AddTimerSeconds(seconds int64, handler Handler) TimerID

AddTimerSeconds is used to set a non recurring timer, that will fire after the seconds supplied. It requires seconds supplied as int64 and at the end the callback to be fired at the desired time.

func (*Anagent) Emit

func (a *Anagent) Emit(event interface{}) *Anagent

Emit Emits an event, it does accept only the event as argument, since the callback will have access to the service mapped by the injector

func (*Anagent) EmitSync

func (a *Anagent) EmitSync(event interface{}) *Anagent

EmitSync Emits an event in a syncronized manner, it does accept only the event as argument, since the callback will have access to the service mapped by the injector

func (*Anagent) Emitter

func (a *Anagent) Emitter() *emission.Emitter

Emitter returns the internal *emission.Emitter used structure use this to access directly to the Emitter, and override the dependency-injection features

func (*Anagent) GetTimer

func (a *Anagent) GetTimer(id TimerID) *Timer

GetTimer is used to set a get a timer from the loop. It requires a TimerID

func (*Anagent) Handlers

func (a *Anagent) Handlers(handlers ...Handler)

Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers, and panics if any of the handlers is not a callable function

func (*Anagent) IsStarted

func (a *Anagent) IsStarted() bool

IsStarted returns a boolean indicating if we started the loop with Start()

func (*Anagent) Next

func (a *Anagent) Next(handler Handler)

Next adds a middleware Handler to the next tick, and removes it once executed.

func (*Anagent) On

func (a *Anagent) On(event, listener interface{}) *Anagent

On Binds a callback to an event, mapping the arguments on a global level

func (*Anagent) Once

func (a *Anagent) Once(event, listener interface{}) *Anagent

Once Binds a callback to an event, mapping the arguments on a global level It is fired only once.

func (*Anagent) RemoveTimer

func (a *Anagent) RemoveTimer(id TimerID)

RemoveTimer is used to set a remove a timer from the loop. It requires a TimerID

func (*Anagent) RunLoop

func (a *Anagent) RunLoop()

RunLoop starts a loop that never returns

func (*Anagent) SetDuration

func (a *Anagent) SetDuration(id TimerID, after time.Duration) TimerID

SetDuration is used to change the duration of a timer. It requires a TimerID and a time.Duration

func (*Anagent) Start

func (a *Anagent) Start()

Start starts the agent loop and never returns. ( unless you call Stop() )

func (*Anagent) Step

func (a *Anagent) Step()

Step executes an agent step. It is idempotent, and even if there are delays in timings events gets executed in order as a best-effort in respecting setted timers.

func (*Anagent) Stop

func (a *Anagent) Stop()

Stop stops the agent loop, in case Start() was called.

func (*Anagent) Timer

func (a *Anagent) Timer(tid TimerID, ti time.Time, after time.Duration, recurring bool, handler Handler) TimerID

Timer is used to set a generic timer. You have to supply by yourself all the options that normally are exposed with other functions. It requires a TimerID (if empty is supplied, it is created for you), a time.Time indicating when the timer have to be fired, a time.Duration indicating the recurring span a boolean to set it as recurring or not and at the end the callback to be fired at the desired time.

func (*Anagent) TimerSeconds

func (a *Anagent) TimerSeconds(seconds int64, recurring bool, handler Handler) TimerID

TimerSeconds is used to set a timer, that will fire after the seconds supplied. It requires seconds supplied as int64 a bool indicating if it is recurring or not, and at the end the callback to be fired at the desired time.

func (*Anagent) Use

func (a *Anagent) Use(handler Handler)

Use adds a middleware Handler to the stack, and panics if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added.

type Handler

type Handler interface{}

Handler can be any callable function. Anagent attempts to inject services into the handler's argument list, and panics if an argument could not be fulfilled via dependency injection.

type Timer

type Timer struct {
	// contains filtered or unexported fields
}

Timer represent the structure that holds the informations of the Timer timer it's a time.Time structure that defines when the timer should be fired, after contains the time.Duration of the recurring timer.

func (*Timer) After

func (t *Timer) After(ti time.Duration)

After receives a time.Duration as arguments, and sets the timer recurring time.

type TimerID

type TimerID string

TimerID is a string that represent the timers ID, it is used so we can access to them later or modify them during the agent execution.

Jump to

Keyboard shortcuts

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