0
votes

So I want to create a simple food order service, but this service require some information from the other service so I use saga pattern. Here's how it should work if I order a food, first it will attempt to create order but if there's any error it will retry for 3 times and publish either success or failed event.
Here's the sample code.

@Saga
class OrderCreationSaga {

  @Transient
  @Autowired
  private lateinit var commandGateway: CommandGateway

  @Transient
  @Autowired
  private lateinit var eventScheduler: EventScheduler

  @Transient
  @Autowired
  private lateinit var eventBus: EventBus

  @Transient
  @Autowired
  private lateinit var scheduleToken: ScheduleToken

  private lateinit var orderId: String
  private var retryCounter = 1

  @StartSaga
  @SagaEventHandler(associationProperty = "orderId")
  fun on(event: OrderCreationAttempted) {
    this.orderId = event.orderId
    eventBus.publish(GenericEventMessage(event.toOrderCreationRequested()))
  }

  @SagaEventHandler(associationProperty = "orderId")
  fun on(event: OrderCreationRequested) {
    try {
      // send data to another service
      orderCreationService.createOrder(event).block()
      eventBus.publish(GenericEventMessage(
        OrderCreationSuccess(
          orderId = event.orderId
        ))
      )
    } catch (error: Throwable) {
      // catching request error, retry for 3 times
      if (this.retryCounter == 3) {
        eventBus.publish(GenericEventMessage(
          OrderCreationFailed(
            orderId = this.orderId,
          )
        ))
      } else {
        eventBus.publish(GenericEventMessage(
          OrderCreationRetry(
            orderId = event.orderId,
          )
        ))
        this.retryCounter++
      }
    }
  }
  
  @EndSaga
  @SagaEventHandler(associationProperty = "orderId")
  fun on(event: OrderCreationSuccess) {
    // do the success job
  }
  
  @EndSaga
  @SagaEventHandler(associationProperty = "orderId")
  fun on(event: OrderCreationFailed) {
    // do the failed job
  }

  @SagaEventHandler(associationProperty = "orderId")
  fun on(event: OrderCreationRetry) {
    val duration = Duration.ofSeconds(30)
    val scheduleEvent = OrderCreationRequested(orderId = event.orderId)
    scheduleToken = eventScheduler.schedule(duration, scheduleEvent)
  }
}

But the weird thing happens so after it published a success event it will publish a OrderCreationRequested event again for some reason (I know this because I've checked the event log inside axonserver). This keeps looping infinitely, is this because my code or some configuration or could be something else?

1
That's an interesting issue you're having there @Patrick. Firstly, can you provide the framework and server version you are using? Furthermore, which instance of the EventScheduler have you configured right now? And lastly, do you per chance have a sample project where I/somebody else can consistently replay the issue?Steven
Nevermind I have fixed it already. The problem caused by someone just hacked my db and start deleting all the data so the tracking token has been reset and all event start reruning again.Patrick
Wow alright, doesn't sound to pleasant that somebody simply hacked your set up to be honest. Happy that you found the culprit though. Might be worth marking that as the solution to this question, so that others reading this will understand what went wrong too.Steven
Nice to see everything is already fixed by you @Patrick ... do you mind adding your own solution to stackoverflow? In this case, we do not have to look into it looking for a solution anymore.Lucas Campos
Sure, I already added the solution. hope it helpful.Patrick

1 Answers

0
votes

So the problem was I forgot to set my username and password for my MongoDB and then someone just trying to delete all of my data including tracking token for axon-server. So because of the tracking token has been delete axon-server start creating the new one with 0 value which makes all the event start rerunning again and again. I solve this problem by just add the username and password for my MongoDB.