Package com.catify.processengine.core.nodes

Source Code of com.catify.processengine.core.nodes.NodeUtils

/**
* *******************************************************
* Copyright (C) 2013 catify <info@catify.com>
* *******************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*         http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.catify.processengine.core.nodes;

import static akka.dispatch.Futures.sequence;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

import scala.concurrent.Await;
import scala.concurrent.ExecutionContext;
import scala.concurrent.Future;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.dispatch.Futures;
import akka.dispatch.OnFailure;
import akka.dispatch.OnSuccess;
import akka.pattern.Patterns;
import akka.util.Timeout;

import com.catify.processengine.core.messages.CommitMessage;
import com.catify.processengine.core.messages.DeactivationMessage;

/**
* Util class for common operations like sending deactivation messages to other nodes
* or to create commit messages used between Event and EvenDefinition.
*
* @author christopher köster
*
*/
@Configurable
public class NodeUtils {
 
  static final Logger LOG = LoggerFactory.getLogger(NodeUtils.class);
 
  @Autowired
  protected ActorSystem actorSystem;
 
  /**
   * Create a commit message with a given future.
   * @param <T>
   *
   * @param future the future
   * @param processInstanceId the process instance id
   * @param self the self actor reference
   * @param sender the sender actor reference
   * @return the commit message
   */
  public <T> CommitMessage<T> createCommitMessage(Future<T> future, String processInstanceId, ActorRef self, ActorRef sender) {
    return new CommitMessage<T>(future, processInstanceId, self.toString(), sender.toString());
  }
 
  /**
   * Create a commit message with a 'successful' future. The future will be generated.
   *
   * @param processInstanceId the process instance id
   * @param self the self actor reference
   * @param sender the sender actor reference
   * @return the commit message
   */
  public CommitMessage<String> createSuccessfulCommitMessage(String processInstanceId, ActorRef self, ActorRef sender) {
    return new CommitMessage<String>(Futures.successful("Successful commit"), processInstanceId, self.toString(), sender.toString());
  }
 
  /**
   * Create a commit message with a 'failed' future and the given failure.
   *
   * @param failure the failure
   * @param processInstanceId the process instance id
   * @param self the self actor reference
   * @param sender the sender actor reference
   * @return the commit message
   */
  public CommitMessage<?> createFailedCommitMessage(Throwable failure, String processInstanceId, ActorRef self, ActorRef sender) {
    return new CommitMessage<Object>(Futures.failed(failure), processInstanceId, self.toString(), sender.toString());
  }
 
  /**
   * Reply commit message.
   *
   * @param commitMessage the commit message
   * @param self the self actor reference
   * @param sender the sender actor reference to reply to
   */
  public void replyCommitMessage(CommitMessage<?> commitMessage, ActorRef self, ActorRef sender) {
    sender.tell(commitMessage, self);
  }
 
  /**
   * Reply a CommitMessage with a 'successful' future. The future will be generated.
   *
   * @param processInstanceId the process instance id
   * @param self the self actor reference
   * @param sender the sender actor reference to reply to
   */
  public void replySuccessfulCommit(String processInstanceId, ActorRef self, ActorRef sender) {
    this.replyCommitMessage(this.createSuccessfulCommitMessage(
        processInstanceId, self, sender), self, sender);
  }
 
  /**
   * Deactivate nodes via DeactivationMessages.
   *
   * @param actorReferences the actor references to deactivate
   * @param processInstanceId the process instance id
   * @param deactivationTimeout the deactivation timeout
   * @param sender the sender actor reference to reply to
   * @param self the self actor reference
   * @return the future sequence
   */
  public Future<Iterable<Object>> deactivateNodes(Iterable<ActorRef> actorReferences, String processInstanceId, Timeout deactivationTimeout, ActorRef sender, ActorRef self) {
   
    final ExecutionContext ec = actorSystem.dispatcher();
   
    Future<Iterable<Object>> futureSequence = sendDeactivationMessageToActors(
        actorReferences, processInstanceId, deactivationTimeout);
        // block until all futures came back
    try {
      Await.result(futureSequence, deactivationTimeout.duration());
      handleDeactivationSuccess(deactivationTimeout, ec, futureSequence, self);
      return futureSequence;
    } catch (Exception e) {
      handleDeactivationSuccess(deactivationTimeout, ec, futureSequence, self);
      return futureSequence;
    }
  }

  /**
   * Send deactivation messages to actors.
   *
   * @param actorReferences the actor references
   * @param processInstanceId the process instance id
   * @param deactivationTimeout the deactivation timeout
   * @return the future
   */
  private Future<Iterable<Object>> sendDeactivationMessageToActors(
      Iterable<ActorRef> actorReferences, String processInstanceId,
      Timeout deactivationTimeout) {
    final ExecutionContext ec = actorSystem.dispatcher();

    List<Future<Object>> listOfFutureActorRefs = new ArrayList<Future<Object>>();
   
    for (ActorRef actor : actorReferences) {
      try {
        // make an asynchronous request ('Patterns.ask') to the event definition actor
        listOfFutureActorRefs.add(Patterns.ask(actor, new DeactivationMessage(processInstanceId), deactivationTimeout));
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
   
    // compose the sequence of the received commit futures
        Future<Iterable<Object>> futuresSequence = sequence(listOfFutureActorRefs, ec);
    return futuresSequence;
  }
 
  /**
   * Handle deactivation success and print appropriate error logs.
   *
   * @param deactivationTimeout the deactivation timeout
   * @param ec the ExecutionContext
   * @param futureSequence the future sequence
   * @param self the self actor reference
   */
  private void handleDeactivationSuccess(final Timeout deactivationTimeout,
      final ExecutionContext ec,
      final Future<Iterable<Object>> futureSequence, final ActorRef self) {

    futureSequence.onSuccess(new OnSuccess<Iterable<Object>>() {
        public void onSuccess(Iterable<Object> result) {
          LOG.debug(String.format("Successfully deactivated other nodes - Deactivation initiated by %s.", self));
        }
      }, ec);
   
    futureSequence.onFailure(new OnFailure() {
        public void onFailure(Throwable failure) {
          if (failure instanceof TimeoutException) {
            LOG.error(String.format("Timeout while waiting for deactivation commits - Deactivation initiated by %s. Timeout was set to %s",
                self, deactivationTimeout.duration()));
          } else {
            failure.printStackTrace();
          }
        }
      }, ec);
  }
}
TOP

Related Classes of com.catify.processengine.core.nodes.NodeUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.