Class: LiveResource::RemoteMethodDispatcher

Inherits:
Object
  • Object
show all
Includes:
LogHelper
Defined in:
lib/live_resource/methods/dispatcher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from LogHelper

#logger, #logger=

Constructor Details

#initialize(resource) ⇒ RemoteMethodDispatcher

Returns a new instance of RemoteMethodDispatcher.



10
11
12
13
14
15
16
# File 'lib/live_resource/methods/dispatcher.rb', line 10

def initialize(resource)
  @resource = resource
  @thread = nil
  @running = false

  start
end

Instance Attribute Details

#resourceObject (readonly)

Returns the value of attribute resource.



8
9
10
# File 'lib/live_resource/methods/dispatcher.rb', line 8

def resource
  @resource
end

#threadObject (readonly)

Returns the value of attribute thread.



8
9
10
# File 'lib/live_resource/methods/dispatcher.rb', line 8

def thread
  @thread
end

Instance Method Details

#redisObject



18
19
20
# File 'lib/live_resource/methods/dispatcher.rb', line 18

def redis
  @resource.redis
end

#runObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/live_resource/methods/dispatcher.rb', line 47

def run
  info("#{self} method dispatcher starting")

  # Register methods and attributes used by this resource class
  redis.register_methods @resource.remote_methods
  redis.register_attributes @resource.remote_attributes

  # Need to register our class and instance in Redis so the finders
  # (all, any, etc.) will work.
  redis.register

  @running = true

  begin
    loop do
      token = redis.method_wait

      if is_exit_token(token)
        if token == exit_token
          redis.method_done token
          break
        else
          redis.method_push token
          next
        end
      end

      method = redis.method_get(token)

      begin
        result = validate_method(method).call(*method.params)

        if result.is_a? Resource
          # Return descriptor of a resource proxy instead
          result = ResourceProxy.new(
            result.redis.redis_class,
            result.redis.redis_name)
        elsif result.is_a? RemoteMethodForward
          # Append forwarding instructions to current method
          method.forward_to result
        end

        if method.final_destination?
          redis.method_result method, result
        else
          # Forward on to next step in method's path
          dest = method.next_destination!

          unless result.is_a? RemoteMethodForward
            # First parameter(s) to next method will be the result
            # of this method call.
            if result.is_a? Array
              method.params = result + method.params
            else
              method.params.unshift result
            end
          end

          dest.remote_send method
        end
      rescue Exception => e
        # TODO: custom encoding for exception to make it less
        # Ruby-specific.

        debug "Method #{method.token} failed:", e.message
        redis.method_result method, e
      end

      redis.method_done token
      redis.method_discard_result(token) if method.flags[:discard_result]
    end
  ensure
    # NOTE: if this process crashes outright, or we lose network
    # connection to Redis, or whatever -- this decrement won't occur.
    # Supervisor should clean up where possible.
    redis.unregister

    info("#{self} method dispatcher exiting")

  end
end

#running?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/live_resource/methods/dispatcher.rb', line 37

def running?
  (@thread != nil) && @running
end

#startObject



22
23
24
25
26
# File 'lib/live_resource/methods/dispatcher.rb', line 22

def start
  return if @thread

  @thread = Thread.new { run }
end

#stopObject



28
29
30
31
32
33
34
35
# File 'lib/live_resource/methods/dispatcher.rb', line 28

def stop
  return if @thread.nil?

  redis.method_push exit_token
  @running = false
  @thread.join
  @thread = nil
end

#wait_for_runningObject



41
42
43
44
45
# File 'lib/live_resource/methods/dispatcher.rb', line 41

def wait_for_running
  while !running? do
    Thread.pass
  end
end