haxeda

EDA-Implementation in Haxe
https://gitlab.com/dani_987/haxeda

To install, run:

haxelib install haxeda 1.1.0 

See using Haxelib in Haxelib documentation for more information.

README.md

HaxEDA

Haxe-EDA implementation.

Install

haxelib install haxeda

Write your Tests

Use haxeda-test to write your Tests. There is also information about how to write them.

Write your business logic

First, lookup how to write some tests and create your first tastcase. Some functions created for the tests will be used in the business logic as well.

1. Create, bind listeners and start the EventEngine ate the application start

In the main method, you can instance the EventEngine, Bind all listeners to it and start the event Engine:

import haxeda.EventEngine;
class Main {
    public static function main() {
        var eventEngine = new EventEngine();
        var registerer = new MyEventEngineRegisterer();
        registerer.registerToEventEngine(eventEngine);
        eventEngine.start(RunTilNoneWaiting);
    }
}

First, get the EventEngineRegisterer you have already created in the tests. Then let it register to the new created EventEngine using registerToEventEngine. Because you haven't passed the isTest-flag, it will be default to false.

During creation of the EventEngine (new EventEngine(eventSaver)), you can pass a haxeda.persistent.EventSaver. It will store all you events and you can use it to restore the last state. For example you can use the haxeda.persistent.DefaultEventSaver, that one will save everything into a json-file. If one is passed, it will be use to save the Events, so no Data is lost after Shutdown. Adding it to the EventEngine will automaticlly restore everything.

As last step, just call start on the EventEngine. This will trigger the Event ApplicationStarted as well. The parameter tells, when the if the EventEngine should terminate: - RunTilKillEvent runs until the event haxeda.events.ApplicationExit was send - RunTilNoneWaiting runs until every event were processed (if some Events were in Status Waiting, the engine keeps running) - RunTilReturns runs until every listener got called (its possible, that the engine will terminate, but the are still some events in Status Waiting).

2. Create Listeners with @listener

To create listener functions, you have create classes the implements the EventListener interface. Inside the Class you can create listener functions by adding @listener to it. The function has to expect only one parameter as the event and return a EventProcessingResult: - Success indicates, that the event was processed without anny errors - StopProcessing(retryInMs) indicates, that this class should stop processing and reprocess the same event in retryInMs. - WithError(errorString) stops processing this and further events in the same class. Its currently only for future use, when unlocking will be implemented

To listen to events it has to call the method registerToEventEngine, it will be generated when implementing haxeda.EventListener:

class SomeListerner implements haxeda.EventListener{
    private var eventEngine: haxeda.EventEngine;
	public function new(eventEngine: haxeda.EventEngine){
		this.eventEngine = eventEngine;
		this.registerToEventEngine(eventEngine);
	}

	@listener
	public function onGettingSomeEvent(ev:SomeEvent) : haxeda.EventListener.EventProcessingResult {
		//Do some processing
        this.eventEngine.triggerEvent(new SomeEventDone());
		return Success;
	}
}

Defining the Events

The events has to implement the Event interface, for example see the simple haxeda.events.ApplicationStarted event:

package haxeda.events;

class ApplicationStarted implements haxeda.Event {
    public function new(){}
}

Autoupdate Data with events

You can use the @update to autoupdate data from any event:

class SomeListerner implements haxeda.EventListener{
    @update var someGlobalValue : String = "";
    //register to eventengine
}
class UpdateGlobalData implements haxeda.Event {
    @update var someGlobalValue : String;
    public function new(valueToSend : String){
        this.someGlobalValue = valueToSend;
    }
}

By sending a UpdateGlobalData all registered haxeda.EventListener's variables of type String named someGlobalValue with @update will receive the data, no listener needs to be implemented for this.

You can also keep track of an Array of Objects. For example we need some personal data of different users.

We can create a PersonListener:

struct Person {
    firstName: String,
    secoundName: String,
    familyName: String,
};
struct FullPerson { > Person, tel: String };
class DataDeleteKeyListerner implements EventListener{
	@keyTable("person") var email : String = "";
	@keyTable("person") var personName : { firstName: String, familyName: String };
	@keyTable("person") var person : Person;
	@keyTable("person") var fullperson : FullPerson;
	@keyTable("person") var mailperson : { > Person, email: String };
    //register to eventengine
}

Now lets create an event, that updates the name and the email:

class UpdateKeyValueData implements haxeda.Event {
    @update var firstName : String;
    @update var email : String;
    @key var person : String;

    public function new(personId: String, name: String, mail: String){
        this.person = personId;
        this.firstName = name;
        this.mail = mail;
    }
}

On sending this Event, you update - email[ev.person] = ev.mail - mailperson[ev.person].email = ev.mail - personName[ev.person].firstName = ev.firstName - person[ev.person].firstName = ev.firstName - fullperson[ev.person].firstName = ev.firstName - mailperson[ev.person].firstName = ev.firstName

If the person doesn't exist, it will be created. To delete a person, you need the following Event:

class DeletePerson implements haxeda.Event {
    @deleteKey var person : String;
    public function new(personId: String){
        this.person = personId;
    }
}

@keyTable variables of type T can be accessed like any normal Map<String,T>, in fact it will be compiled into a Map<String,T>.

Sending Events

You can send events by using the triggerEvent method, see this example:

class SomeListener implements haxeda.EventListener{
	private var eventEngine: haxeda.EventEngine;
    public function new(eventEngine: haxeda.EventEngine){
		this.eventEngine = eventEngine;
		this.registerToEventEngine(eventEngine);
	}

    @listener
	public function onDoSomeWork(someWork:DoSomeWork) : haxeda.EventListener.EventProcessingResult {
        var result = this.doSomeWork(someWork);
		this.eventEngine.triggerEvent(new WorkDone(result));
        if(result){
		    return Success;
        } else {
		    return StopProcessing(2000);
        }
	}
}

You don't have to send events from a listener, it can be send from any place you want.

Other methods to create listeners

You can also create a listener function without @listener. It will not be bound to the EventEngine by calling this.registerToEventEngine(eventEngine);. You still have to call this.registerToEventEngine(eventEngine); to auto update @update or @keyTable variables.

class SomeListerner implements haxeda.EventListener{
	public function new(eventEngine: haxeda.EventEngine){
        //call this.registerToEventEngine(eventEngine) and do other stuff
        eventEngine.registerFunction(SomeEvent, this, onGettingSomeEvent);
	}

	public function onGettingSomeEvent(ev:SomeEvent) : haxeda.EventListener.EventProcessingResult {
		//Do some processing
        this.eventEngine.triggerEvent(new SomeEventDone());
		return Success;
	}
}

Also you can create a Listener for all events:

class SomeListerner implements haxeda.EventListener{
	public function new(eventEngine: haxeda.EventEngine){
        //call this.registerToEventEngine(eventEngine) and do other stuff
        eventEngine.registerFunction(SomeEvent, this, onGettingSomeEvent);
	}

	public function onGettingSomeEvent(ev:SomeEvent) : haxeda.EventListener.EventProcessingResult {
		//Do some processing
        this.eventEngine.triggerEvent(new SomeEventDone());
		return Success;
	}
}

Register and Unregister Listeners

You can use eventEngine.registerFunction(Event, Listener, ListenerFun) to register an Function to an Event or eventEngine.removeFunction(Event, Listener, ListenerFun) to remove the function. The Parameters of eventEngine.removeFunction(Event, Listener, ListenerFun) has to have the same value like it was used on eventEngine.registerFunction(Event, Listener, ListenerFun)!

You can use eventEngine.registerListener(Listener) to only update the variables and eventEngine.removeListener(Listener) to not update the variables nor call any ListenerFun.

TODOs:

  • API for undoing Events:

    By using the History Data ist should be possible to undo events

Contributors
dani-987
Version
1.1.0
Published
1 year ago
License
MIT

All libraries are free

Every month, more than a thousand developers use Haxelib to find, share, and reuse code — and assemble it in powerful new ways. Enjoy Haxe; It is great!

Explore Haxe

Haxe Manual

Haxe Code Cookbook

Haxe API documentation

You can try Haxe in the browser! try.haxe.org

Join us on GitHub!

Haxe is being developed on GitHub. Feel free to contribute or report issues to our projects.

Haxe on GitHub