Port of https://github.com/redux-saga/redux-saga to C# for Unity3d coroutines. This project is currently in POC phase. Any contributions or ideas are welcomed!
Allows to invoke SagaAction that can be received by multiple other sagas
private IEnumerator RootSaga()
{
yield return Do.Put(new SagaAction<int>("ACTION_NAME", 42));
}
void Start ()
{
var saga = new Saga();
saga.OnActionEvent += Saga_OnActionEvent;
this.StartCoroutine(saga.Run(this.RootSaga()));
}
private void Saga_OnActionEvent(SagaAction data)
{
Debug.Log("The answer is: " + data.GetPayload<int>());
}
Allows to wait for SagaAction to be invoked and then continues execution
private IEnumerator RootSaga()
{
yield return Do.Take("START", action);
}
void Start ()
{
var saga = new Saga();
this.StartCoroutine(saga.Run(this.RootSaga()));
//nothing happens until following line executes
saga.OnAction(new SagaAction<int>("START", 11));
}
Invokes method with a set of parameters
private int TestCallMethod(params object[] args)
{
return 1;
}
private IEnumerator RootSaga()
{
var returnData = new Ref<int>();
yield return Do.Call(TestCallMethod, returnData);
}
void Start ()
{
var saga = new Saga();
this.StartCoroutine(saga.Run(this.RootSaga()));
}
Invokes method with a set of parameters in a separate thread and waits for the result in a non-blocking manner
private int TestCallMethod(params object[] args)
{
Thread.Sleep(4000);
return 1;
}
private IEnumerator RootSaga()
{
var returnData = new Ref<int>();
yield return Do.ThreadCall(TestCallMethod, returnData);
}
void Start ()
{
var saga = new Saga();
this.StartCoroutine(saga.Run(this.RootSaga()));
}
Yields in try/catch can be tricky. This methods tries to solve that.
private int TestCallMethod(params object[] args)
{
throw new NotImplementedException();
}
private IEnumerator DoStuff()
{
var data = new Ref<int>();
yield return Do.Call(TestCallMethod, data);
yield return Do.Put<int>(new SagaAction<int>("SUCCESS", data.Value));
}
private IEnumerator CatchRoutine(Exception exception)
{
yield return Do.Put(new SagaAction<Exception>("ERROR", exception));
}
private IEnumerator FinallyRoutine()
{
yield return Do.Put(new SagaAction<int>("FINALLY", 1));
}
private IEnumerator RootSaga()
{
yield return Do.Try(DoStuff(), CatchRoutine, FinallyRoutine());
}
void Start ()
{
var saga = new Saga();
saga.OnActionEvent += Saga_OnActionEvent;
this.StartCoroutine(saga.Run(this.RootSaga()));
}
private void Saga_OnActionEvent(SagaAction data)
{
Debug.Log("INVOKED_ACTION: " + data.Type);
// prints out:
// "INVOKED_ACTION: ERROR"
// "INVOKED_ACTION: FINALLY"
}
Forks saga into a separate "subprocess" allowing to run multiple sagas simultaneously.
private IEnumerator SagaWithTake()
{
var action = new Ref<SagaAction>();
yield return Do.Take("TEST", action);
yield return Do.Put(new SagaAction<int>("RESULT", action.Value.GetPayload<int>()));
}
private IEnumerator SagaWithPut()
{
yield return Do.Put(new SagaAction<int>("TEST", 123));
}
private IEnumerator RootSaga()
{
yield return Do.Fork(SagaWithTake());
yield return Do.Fork(SagaWithPut());
}
void Start ()
{
var saga = new Saga();
this.StartCoroutine(saga.Run(this.RootSaga()));
}