Code Monkey home page Code Monkey logo

Comments (10)

ShaneCourtrille avatar ShaneCourtrille commented on July 26, 2024

Also another area of interest for us as I too have written code to support something called a 'Saga' which wasn't really a 'Saga' and it is quite painful to maintain.

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

Alrighty then, time to flesh this one out. While doing some research on the 1st app we've targeted to switch to Jasper I noticed that it was using sagas, so time to move this up.

Basic syntax ideas:

// Base class that marks the handler type as a stateful saga,
// where "T" is the state type for the saga.
public abstract class Saga<T>
{
    public bool IsCompleted {get;set;}

    public void MarkCompleted()
    {
        IsCompleted = true;
    }
}

public class InvoiceSaga : Saga<Invoice>
{
   public T Starts(Message1)
   {
       // do stuff
   }

   // or
   public Task<T> Starts(Message1)
   {

   }

   // Can use Handle/Consume() methods for other actions as normal
   // Also use Orchestrates() to be compatible w/ previous FubuMVC code

   // Jasper will generate code that will look up the saga state object for the message
   // type and pass that into the method here
   public void Handles(Message message, Invoice invoice)
   {

   }

   // Need some way to pick off the identity for the saga state object
   // from the incoming message. This is one possibility. 
   // If we do this, it will honor base types
   // Thinking that we'd support Guid, int, long, and string as valid identity
   // types
   public Guid Identity(Message message) => message.SagaId;
}

public class Envelope
{
    // If you don't wanna have to stick the saga id inside the messages
    // Gonna be a little annoying to track this, but have it set in cascading messages
    public string SagaId {get;set;}
}

Tasks:

  • Discover handler actions on classes that inherit from Saga<T>
  • Track SagaId on envelopes in cascading messages
  • Policy that wraps saga persistence BlueMilk frames around the handlers
  • Marten-backed saga persistence. Codegen in the handling around it
  • Find the saga identity from message.SagaId (convention)
  • Respect a [SagaId] attribute on the message types as another alternative
  • Find the saga identity from HandlerClass.Identity(message type)
  • Respect the Creates() methods
  • Respect the IsCompleted() method and handling

from jasper.

mike-schenk avatar mike-schenk commented on July 26, 2024

This description matches what I remember from the conversation. A few questions though:

  • What will the Creates() method do?
  • Does the Envelope.SagaId identify the saga that is receiving the message, or the one that is sending it? For example, if saga A sends a message that starts saga B, and saga B's Starts method returns a message back to saga A, which SagaId is in that response message envelope?
  • Do we still want to call it a "saga" to match common usage even though it won't include built-in support for rollback/compensation like the original definition of a saga would? Or is this a good opportunity to name it based on the process manager pattern which seems to be a better description?

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

@mike-schenk,

Sorry for the delay.

Creates() was meant to be "initiates the long running saga". If that's confusing, I'd go for "Start()" instead, but definitely not "Initiates()" 'cause folks would never spell it right. Could just say that any Handler method that returns the Saga state object is a de facto creator, but I think that'd be confusing

Envelope.SagaId would be the current saga id referring to the state of the saga. If we have the tracking to the original & parent envelope id's, we have some way of correlating everything in the end, so I'd probably just leave that be. I'm not nearly as worried about forcing users to have the saga id somewhere in the message bodies.

As for the naming, I think far more people are going to be familiar with "saga" in terms of service bus tooling where it's really just a stateful, long running process.

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

Meh, I'm going to push this one off to a future 0.7.0 release. I hate trying to even do this w/o any kind of early adopter or sample apps first.

from jasper.

ShaneCourtrille avatar ShaneCourtrille commented on July 26, 2024

Can you give an example of how you see Creates() working? In our internal Saga code we went with the idea of the marker interface which starts a new saga. I'm curious how this would differ?

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

@ShaneCourtrille It would work the same way. The naming convention just tips Jasper off that this starts a brand new saga of this type. Using the naming convention also lets you have multiple entry points to start the stateful saga

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

@ShaneCourtrille And I think I'll call it "Start" instead.

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

Now then, how do we find the saga state Id for a message? I think in this order:

  1. SagaId property on the envelope, which would be a new "saga-id" header
  2. SagaId property on the message type
  3. [SagaId] attribute on a property on the message type
  4. Identity(message) method on the handler type

from jasper.

jeremydmiller avatar jeremydmiller commented on July 26, 2024

The basic support for Marten-backed sagas is done in ceb43c1.

I'll be opening additional issues for Sql Server backed persistence and there are a bunch of others for "advanced" usages and hardening the usage.

from jasper.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.