private void assignEventToScheduler(T task, Object sequenceIdentifier) {
   boolean taskScheduled = false;
   while (!taskScheduled) {
     EventProcessingScheduler<T> currentScheduler = transactions.get(sequenceIdentifier);
     if (currentScheduler == null) {
       transactions.putIfAbsent(
           sequenceIdentifier, newProcessingScheduler(new TransactionCleanUp(sequenceIdentifier)));
     } else {
       taskScheduled = currentScheduler.scheduleEvent(task);
       if (!taskScheduled) {
         // we know it can be cleaned up.
         transactions.remove(sequenceIdentifier, currentScheduler);
       }
     }
   }
 }
 /**
  * Schedules this task for execution when all pre-conditions have been met.
  *
  * @param task The task to schedule for processing.
  */
 protected void schedule(T task) {
   final Object sequenceIdentifier = sequencingPolicy.getSequenceIdentifierFor(task);
   if (sequenceIdentifier == null) {
     logger.debug(
         "Scheduling task of type [{}] for full concurrent processing",
         task.getClass().getSimpleName());
     EventProcessingScheduler<T> scheduler =
         newProcessingScheduler(new NoActionCallback(), this.concurrentEventQueue);
     scheduler.scheduleEvent(task);
   } else {
     logger.debug(
         "Scheduling task of type [{}] for sequential processing in group [{}]",
         task.getClass().getSimpleName(),
         sequenceIdentifier.toString());
     assignEventToScheduler(task, sequenceIdentifier);
   }
 }