lib/aws/simple_workflow.rb



# Copyright 2011-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
#     http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file 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.

require 'aws/core'
require 'aws/simple_workflow/config'

module AWS

  # This is the starting point for working with Amazon Simple Workflow Service.
  #
  # = Domains
  #
  # To get started, you need to first create a domain.  Domains are used to 
  # organize related tasks and activities.  
  #
  #   swf = AWS::SimpleWorkflow.new
  #
  #   # name the domain and specify the retention period (in days)
  #   domain = swf.domains.create('my-domain', 10)
  #
  # You can reference existin domains as well.
  #
  #   domain = swf.domains['my-domain']
  #
  # = Workflow and Activity Types
  #
  # Once you have a domain you can create a workflow and
  # activity types.  Both types (workflow and activity) are templates that
  # can be used to start workflow executions or schedule activity tasks.
  #
  # Workflow and Acitivity types both have a number of default values
  # (e.g. default task list, timeouts, etc).  If you do not specify these
  # optional default values when creating the type, you *MUST* specify
  # the actual values when starting a workflow execution or scheduling
  # an activity task.
  #
  # == Sample Workflow type and activity type
  #
  #   # register an workflow type with the version id '1'
  #   workflow_type = domain.workflow_types.create('my-long-processes', '1',
  #     :default_task_list => 'my-task-list',
  #     :default_child_policy => :request_cancel,
  #     :default_task_start_to_close_timeout => 3600,
  #     :default_execution_start_to_close_timeout => 24 * 3600)
  # 
  #   # register an activity type, with the version id '1'
  #   activity_type = domain.activity_types.create('do-something', '1', 
  #     :default_task_list => 'my-task-list',
  #     :default_task_heartbeat_timeout => 900,
  #     :default_task_schedule_to_start_timeout => 60,
  #     :default_task_schedule_to_close_timeout => 3660,
  #     :default_task_start_to_close_timeout => 3600)
  #
  # = Starting a Workflow Execution
  #
  # Once you have a domain and at least one workflow type you can
  # start a workflow execution.  You may provide a workflow id, or a
  # random one will be generated.  You may also provide optional
  # input and override any of the defaults registered with the 
  # workflow type.
  #
  #   workflow_execution = workflow_type.start_execution :input => '...'
  #
  #   workflow_execution.workflow_id #=> "5abbdd75-70c7-4af3-a324-742cd29267c2"
  #   workflow_execution.run_id #=> "325a8c34-d133-479e-9ecf-5a61286d165f"
  #
  # = Decision Tasks
  #
  # Once a workflow execution has been started, it will start to generte
  # decision tasks.  You poll for decision tasks from a task list.
  # Yielded decsion tasks provide access to the history of events 
  # for the workflow execution.  You can also enumerate only new
  # events since the last decision.
  # 
  # To make decisions you call methods from the list below.  You can call
  # any number of decision methods any number of times.
  #
  # * schedule_activity_task
  # * request_cancel_activity_task
  # * complete_workflow_execution
  # * fail_workflow_execution
  # * cancel_workflow_execution
  # * continue_as_new_workflow_execution
  # * record_marker
  # * start_timer
  # * cancel_timer
  # * signal_external_workflow_execution
  # * request_cancel_external_workflow_execution workflow_execution, options = {}
  # * start_child_workflow_execution workflow_type, options = {}
  #
  # This sample gets a decision task and responds based on the events
  # by scheduling an activity task or completing the workflow execution.
  #
  #   # poll for decision tasks from 'my-task-list'
  #   domain.decision_tasks.poll('my-task-list') do |task|
  #
  #     # invesitate new events and make decisions
  #     task.new_events.each do |event|
  #       case event.event_type
  #       when 'WorkflowExecutionStarted'
  #         task.schedule_activity_task 'do-something', :input => 'abc xyz'
  #       when 'ActivityTaskCompleted'
  #         task.complete_workflow_execution :result => event.attributes.result
  #       end
  #     end
  #
  #   end # decision task is completed here
  #
  # When you are done calling decision methods, you need to complete the
  # decision task.  This is done by default if you pass a block to
  # +poll+ or +poll_for_single_task+.
  #
  # = Activity Tasks
  #
  # The only way to spawn activity tasks is to call +schedule_activity_task+
  # on a decision task.  Scheduled activity tasks are returned when you
  # poll for activity tasks.
  #
  #   # poll 'my-task-list' for activities
  #   domain.activity_tasks.poll('my-task-list') do |activity_task|
  #
  #     case activity_task.activity_type.name
  #     when 'do-something' 
  #       # ...
  #     else
  #       activity_task.fail! :reason => 'unknown activity task type'
  #     end
  #     
  #   end
  #
  # == Activity Task Heartbeats
  #
  # When you receive an activity task, you need to update the service
  # with status messages.  This is called recording a heartbeat.#
  # To record a heartbeat, just call {ActivityTask#record_heartbeat!}.  
  # When you call +record_heartbeat+ you should rescue 
  # {ActivityTask::CancelRequestedError}.  These are thrown when a task
  # should be canceled.  You can cleanup the task and then call 
  # +cancel!+ when you are finished.
  #
  #   # poll 'my-task-list' for activities
  #   domain.activity_tasks.poll('my-task-list') do |activity_task|
  #     begin
  #
  #       # do stuff ...
  #
  #       activity_task.record_heartbeat! :details => '25%'
  #
  #       # do more stuff ...
  #
  #       activity_task.record_heartbeat! :details => '50%'
  #
  #       # do more stuff ...
  #
  #       activity_task.record_heartbeat! :details => '75%'
  #
  #       # do more stuff ...
  #
  #     rescue ActivityTask::CancelRequestedError
  #       # cleanup after ourselves
  #       activity_task.cancel!
  #     end
  #   end
  #   
  # Like decision tasks, activity tasks are auto-completed at the 
  # end of a poll block.
  #
  # = History Events
  #
  # You might want to view the event history for a running workflow
  # execution.  You can get a workflow execution by its workflow
  # id (you may optionally provide the run id as well).
  #
  #   execution = domain.workflow_executions['workflow-id']
  #   execution.events.each do |event|
  #     puts event.attributes.to_h.inspect
  #   end
  #
  # See {HistoryEvent} and {HistoryEvent::Attributes} for more information.
  #
  class SimpleWorkflow

    AWS.register_autoloads(self, 'aws/simple_workflow') do
      autoload :ActivityType,                'activity_type'
      autoload :ActivityTypeCollection,      'activity_type_collection'
      autoload :ActivityTask,                'activity_task'
      autoload :ActivityTaskCollection,      'activity_task_collection'
      autoload :Client,                      'client'
      autoload :Count,                       'count'
      autoload :DecisionTask,                'decision_task'
      autoload :DecisionTaskCollection,      'decision_task_collection'
      autoload :Domain,                      'domain'
      autoload :DomainCollection,            'domain_collection'
      autoload :Errors,                      'errors'
      autoload :HistoryEvent,                'history_event'
      autoload :HistoryEventCollection,      'history_event_collection'
      autoload :OptionFormatters,            'option_formatters'
      autoload :Request,                     'request'
      autoload :Resource,                    'resource'
      autoload :Type,                        'type'
      autoload :TypeCollection,              'type_collection'
      autoload :WorkflowExecution,           'workflow_execution'
      autoload :WorkflowExecutionCollection, 'workflow_execution_collection'
      autoload :WorkflowType,                'workflow_type'
      autoload :WorkflowTypeCollection,      'workflow_type_collection'
    end

    include Core::ServiceInterface

    # @return [DomainCollection]
    def domains
      DomainCollection.new(:config => config)
    end

  end
end