# Class: Concurrent::Actor::AbstractContext Abstract

Inherits:
  Object
  - Object
  - Concurrent::Actor::AbstractContext
  show all

Includes:
  InternalDelegations, TypeCheck

Defined in:
  lib/concurrent-ruby-edge/concurrent/actor/context.rb

## Overview

This class is abstract.

implement #on_message and #behaviour_definition

New actor is defined by subclassing RestartingContext, Context and defining its abstract methods. AbstractContext can be subclassed directly to implement more specific behaviour see Root implementation.

- Context

  > Basic Context of an Actor. It supports only linking and it simply terminates on error. Uses Behaviour.basic_behaviour_definition:

- RestartingContext.

  > Context of an Actor for robust systems. It supports supervision, linking, pauses on error. Uses Behaviour.restarting_behaviour_definition

Example of ac actor definition:

    Message = Struct.new :action, :value

    class AnActor < Concurrent::Actor::RestartingContext
      def initialize(init)
        @counter = init
      end

      # override #on_message to define actor's behaviour on message received
      def on_message(message)
        case message.action
        when :add
          @counter = @counter + message.value
        when :subtract
          @counter = @counter - message.value
        when :value
          @counter
        else
          pass
        end
      end

      # set counter to zero when there is an error
      def on_event(event)
        if event == :reset
          @counter = 0 # ignore initial value
        end
      end
    end

    an_actor = AnActor.spawn name: 'an_actor', args: 10
    an_actor << Message.new(:add, 1) << Message.new(:subtract, 2)
    an_actor.ask!(Message.new(:value, nil))            # => 9
    an_actor << :boo << Message.new(:add, 1)
    an_actor.ask!(Message.new(:value, nil))            # => 1
    an_actor << :terminate!
        # => #<Concurrent::Actor::Reference:0x7fbedc137688 /an_actor (AnActor)>

See methods of AbstractContext what else can be tweaked, e.g #default_reference_class

## Direct Known Subclasses

Context, RestartingContext, Root

## Instance Attribute Summary collapse

- #core ⇒ undocumented readonly

## Class Method Summary collapse

- .spawn(name_or_opts, *args, &block) ⇒ undocumented

  Behaves as spawn but :class is auto-inserted based on receiver so it can be omitted.

- .spawn!(name_or_opts, *args, &block) ⇒ undocumented

  behaves as spawn! but :class is auto-inserted based on receiver so it can be omitted.

## Instance Method Summary collapse

- #ask(message) ⇒ undocumented (also: #ask!)
- #behaviour_definition ⇒ Array<Array(Behavior::Abstract, Array<Object>)>
- #dead_letter_routing ⇒ Reference

  Defines an actor responsible for dead letters.

- #default_executor ⇒ Executor

  override to se different default executor, e.g.

- #default_reference_class ⇒ CLass

  override if different class for reference is needed.

- #envelope ⇒ Envelope

  Current envelope, accessible inside #on_message processing.

- #on_envelope(envelope) ⇒ undocumented private
- #on_event(event) ⇒ undocumented

  override to add custom code invocation on internal events like `:terminated`, `:resumed`, `anError`.

- #on_message(message) ⇒ Object abstract

  A result which will be used to set the Future supplied to Reference#ask.

- #pass ⇒ undocumented

  if you want to pass the message to next behaviour, usually Behaviour::ErrorsOnUnknownMessage.

- #tell(message) ⇒ undocumented (also: #<<)

  tell self a message.

- #behaviour(behaviour_class) ⇒ undocumented included from InternalDelegations

  see Core#behaviour.

- #behaviour!(behaviour_class) ⇒ undocumented included from InternalDelegations

  see Core#behaviour!.

- #Child!(value, *types) ⇒ undocumented included from TypeCheck
- #Child?(value, *types) ⇒ Boolean included from TypeCheck
- #children ⇒ undocumented included from InternalDelegations
- #context ⇒ AbstractContext included from InternalDelegations
- #context_class ⇒ undocumented (also: #actor_class) included from PublicDelegations
- #executor ⇒ undocumented included from PublicDelegations
- #log(level, message = nil, &block) ⇒ undocumented included from InternalDelegations

  delegates to core.log.

- #Match!(value, *types) ⇒ undocumented included from TypeCheck
- #Match?(value, *types) ⇒ Boolean included from TypeCheck
- #name ⇒ undocumented included from PublicDelegations
- #parent ⇒ undocumented included from PublicDelegations
- #path ⇒ undocumented included from PublicDelegations
- #redirect(reference, envelope = self.envelope) ⇒ undocumented included from InternalDelegations
- #reference ⇒ undocumented (also: #ref) included from PublicDelegations
- #terminate!(reason = nil) ⇒ undocumented included from InternalDelegations
- #terminated? ⇒ Boolean included from InternalDelegations
- #Type!(value, *types) ⇒ undocumented included from TypeCheck
- #Type?(value, *types) ⇒ Boolean included from TypeCheck

## Instance Attribute Details

### #core ⇒ `undocumented` (readonly)

    28
    29
    30

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 28

    def core
      @core
    end

## Class Method Details

### .spawn(name_or_opts, *args, &block) ⇒ `undocumented`

Behaves as Concurrent::Actor.spawn but :class is auto-inserted based on receiver so it can be omitted.

Examples:

by class and name

    AdHoc.spawn(:ping1) { -> message { message } }

by option hash

    inc2 = AdHoc.spawn(name:     'increment by 2',
                       args:     [2],
                       executor: Concurrent.configuration.global_task_pool) do |increment_by|
      lambda { |number| number + increment_by }
    end
    inc2.ask!(2) # => 4

See Also:

- Concurrent::Actor.spawn

    115
    116
    117

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 115

    def self.spawn(name_or_opts, *args, &block)
      Actor.spawn to_spawn_options(name_or_opts, *args), &block
    end

### .spawn!(name_or_opts, *args, &block) ⇒ `undocumented`

behaves as Concurrent::Actor.spawn! but :class is auto-inserted based on receiver so it can be omitted.

    120
    121
    122

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 120

    def self.spawn!(name_or_opts, *args, &block)
      Actor.spawn! to_spawn_options(name_or_opts, *args), &block
    end

## Instance Method Details

### #ask(message) ⇒ `undocumented` Also known as: ask!

    96
    97
    98

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 96

    def ask(message)
      raise 'actor cannot ask itself'
    end

### #behaviour_definition ⇒ `Array<Array(Behavior::Abstract, Array<Object>)>`

Returns:

- (`Array<Array(Behavior::Abstract, Array<Object>)>`)

Raises:

- (`NotImplementedError`)

    70
    71
    72

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 70

    def behaviour_definition
      raise NotImplementedError
    end

### #dead_letter_routing ⇒ `Reference`

Defines an actor responsible for dead letters. Any rejected message send with Reference#tell is sent there, a message with future is considered already monitored for failures. Default behaviour is to use #dead_letter_routing of the parent, so if no #dead_letter_routing method is overridden in parent-chain the message ends up in `Actor.root.dead_letter_routing` agent which will log warning.

Returns:

- (`Reference`)

    65
    66
    67

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 65

    def dead_letter_routing
      parent.dead_letter_routing
    end

### #default_executor ⇒ `Executor`

override to se different default executor, e.g. to change it to global_operation_pool

Returns:

- (`Executor`)

    87
    88
    89

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 87

    def default_executor
      Concurrent.global_io_executor
    end

### #default_reference_class ⇒ `CLass`

override if different class for reference is needed

Returns:

- (`CLass`) —

  descendant of Reference

    81
    82
    83

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 81

    def default_reference_class
      Reference
    end

### #envelope ⇒ `Envelope`

Returns current envelope, accessible inside #on_message processing.

Returns:

- (`Envelope`) —

  current envelope, accessible inside #on_message processing

    75
    76
    77

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 75

    def envelope
      @envelope or raise 'envelope not set'
    end

### #on_envelope(envelope) ⇒ `undocumented`

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

    44
    45
    46
    47
    48
    49

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 44

    def on_envelope(envelope)
      @envelope = envelope
      on_message envelope.message
    ensure
      @envelope = nil
    end

### #on_event(event) ⇒ `undocumented`

override to add custom code invocation on internal events like `:terminated`, `:resumed`, `anError`.

    40
    41

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 40

    def on_event(event)
    end

### #on_message(message) ⇒ `Object`

This method is abstract.

override to define Actor's behaviour

Note:

self should not be returned (or sent to other actors), PublicDelegations#reference should be used instead

Returns a result which will be used to set the Future supplied to Reference#ask.

Parameters:

- message (`Object`)

Returns:

- (`Object`) —

  a result which will be used to set the Future supplied to Reference#ask

Raises:

- (`NotImplementedError`)

    35
    36
    37

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 35

    def on_message(message)
      raise NotImplementedError
    end

### #pass ⇒ `undocumented`

if you want to pass the message to next behaviour, usually Behaviour::ErrorsOnUnknownMessage

    53
    54
    55

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 53

    def pass
      core.behaviour!(Behaviour::ExecutesContext).pass envelope
    end

### #tell(message) ⇒ `undocumented` Also known as: <<

tell self a message

    92
    93
    94

    # File 'lib/concurrent-ruby-edge/concurrent/actor/context.rb', line 92

    def tell(message)
      reference.tell message
    end

### #behaviour(behaviour_class) ⇒ `undocumented` Originally defined in module InternalDelegations

see Core#behaviour

### #behaviour!(behaviour_class) ⇒ `undocumented` Originally defined in module InternalDelegations

see Core#behaviour!

### #Child!(value, *types) ⇒ `undocumented` Originally defined in module TypeCheck

### #Child?(value, *types) ⇒ `Boolean` Originally defined in module TypeCheck

Returns:

- (`Boolean`)

### #children ⇒ `undocumented` Originally defined in module InternalDelegations

See Also:

- Core#children

### #context ⇒ `AbstractContext` Originally defined in module InternalDelegations

Returns:

- (`AbstractContext`)

### #context_class ⇒ `undocumented` Also known as: actor_class Originally defined in module PublicDelegations

See Also:

- Core#context_class

### #executor ⇒ `undocumented` Originally defined in module PublicDelegations

See Also:

- Core#executor

### #log(level, message = nil, &block) ⇒ `undocumented` Originally defined in module InternalDelegations

delegates to core.log

See Also:

- Logging#log

### #Match!(value, *types) ⇒ `undocumented` Originally defined in module TypeCheck

### #Match?(value, *types) ⇒ `Boolean` Originally defined in module TypeCheck

Returns:

- (`Boolean`)

### #name ⇒ `undocumented` Originally defined in module PublicDelegations

See Also:

- Core#name

### #parent ⇒ `undocumented` Originally defined in module PublicDelegations

See Also:

- Core#parent

### #path ⇒ `undocumented` Originally defined in module PublicDelegations

See Also:

- Core#path

### #redirect(reference, envelope = self.envelope) ⇒ `undocumented` Originally defined in module InternalDelegations

### #reference ⇒ `undocumented` Also known as: ref Originally defined in module PublicDelegations

See Also:

- Core#reference

### #terminate!(reason = nil) ⇒ `undocumented` Originally defined in module InternalDelegations

See Also:

- Termination#terminate!

### #terminated? ⇒ `Boolean` Originally defined in module InternalDelegations

Returns:

- (`Boolean`)

See Also:

- Termination#terminated?

### #Type!(value, *types) ⇒ `undocumented` Originally defined in module TypeCheck

### #Type?(value, *types) ⇒ `Boolean` Originally defined in module TypeCheck

Returns:

- (`Boolean`)