Class: Ractor::Server::Request

Inherits:
Object
  • Object
show all
Extended by:
Debugging
Includes:
Debugging
Defined in:
lib/ractor/server/request.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Debugging

debug

Constructor Details

#initialize(response_to: nil, sync: nil, info: nil) ⇒ Request

Returns a new instance of Request.



14
15
16
17
18
19
20
21
# File 'lib/ractor/server/request.rb', line 14

def initialize(response_to: nil, sync: nil, info: nil)
  @response_to = response_to
  @initiating_ractor = Ractor.current
  @sync = sync
  @info = info # for display only
  enforce_valid_sync!
  Ractor.make_shareable(self)
end

Instance Attribute Details

#infoObject (readonly)

Returns the value of attribute info.



12
13
14
# File 'lib/ractor/server/request.rb', line 12

def info
  @info
end

#initiating_ractorObject (readonly)

Returns the value of attribute initiating_ractor.



12
13
14
# File 'lib/ractor/server/request.rb', line 12

def initiating_ractor
  @initiating_ractor
end

#response_toObject (readonly)

Returns the value of attribute response_to.



12
13
14
# File 'lib/ractor/server/request.rb', line 12

def response_to
  @response_to
end

#syncObject (readonly)

Returns the value of attribute sync.



12
13
14
# File 'lib/ractor/server/request.rb', line 12

def sync
  @sync
end

Class Method Details

.message(*args, **options) ⇒ Object



94
95
96
97
# File 'lib/ractor/server/request.rb', line 94

def message(*args, **options)
  request = new(**options)
  [request, *args].freeze
end

.pending_receive_conclusionObject



103
104
105
# File 'lib/ractor/server/request.rb', line 103

def pending_receive_conclusion
  ::Ractor.current[:ractor_server_request_receive_conclusion] ||= ::ObjectSpace::WeakMap.new
end

.pending_send_conclusionObject



99
100
101
# File 'lib/ractor/server/request.rb', line 99

def pending_send_conclusion
  ::Ractor.current[:ractor_server_request_send_conclusion] ||= ::ObjectSpace::WeakMap.new
end

.receive_if(&block) ⇒ Object



107
108
109
110
111
112
113
# File 'lib/ractor/server/request.rb', line 107

def receive_if(&block)
  message = ::Ractor.receive_if(&block)
  rq, = message
  rq.sync_after_receiving
  debug(:receive) { "Received #{message}" }
  message
end

.send(ractor, *arguments, move: false, **options) ⇒ Object



115
116
117
118
119
120
121
122
# File 'lib/ractor/server/request.rb', line 115

def send(ractor, *arguments, move: false, **options)
  message = Request.message(*arguments, **options)
  request, = message
  request.enforce_sync_when_sending!
  debug(:send) { "Sending #{message}" }
  ractor.send(message, move: move)
  request
end

Instance Method Details

#===(message) ⇒ Object

Match any request that is a response to the receiver (or an array message starting with such)



24
25
26
27
28
29
30
31
32
# File 'lib/ractor/server/request.rb', line 24

def ===(message)
  request, = message

  match = request.is_a?(Request) && self == request.response_to

  debug(:receive) { "Request #{request.inspect} does not match #{self}" } unless match

  match
end

#enforce_sync_when_sending!Object

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.



157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/ractor/server/request.rb', line 157

def enforce_sync_when_sending!
  # Only dynamic checks are done here; static validity checked in constructor
  case sync
  when :conclude, :interrupt
    registry = Request.pending_send_conclusion
    raise Talk::Error, "Request #{response_to} already answered" unless registry[response_to]

    registry[response_to] = false
    Request.pending_receive_conclusion[response_to.response_to] = false if sync == :interrupt
  when :ask, :converse
    Request.pending_receive_conclusion[self] = true
  end
end

#inspectObject Also known as: to_s



76
77
78
79
80
81
82
83
84
# File 'lib/ractor/server/request.rb', line 76

def inspect
  [
    '<Request',
    info,
    ("for: #{response_to}" if response_to),
    ("sync: #{sync}" if sync),
    "from: #{ractor_name(initiating_ractor)}>",
  ].compact.join(' ')
end

#receiveObject



71
72
73
74
# File 'lib/ractor/server/request.rb', line 71

def receive
  enforce_sync_when_receiving!
  unwrap(Request.receive_if(&self))
end

#respond_to_ractorObject



87
88
89
# File 'lib/ractor/server/request.rb', line 87

def respond_to_ractor
  response_to.initiating_ractor
end

#send(*args, **options) ⇒ Request

Returns:



39
40
41
# File 'lib/ractor/server/request.rb', line 39

def send(*args, **options)
  Request.send(initiating_ractor, *args, **options, response_to: self)
end

#send_exception(exception) ⇒ Object



67
68
69
# File 'lib/ractor/server/request.rb', line 67

def send_exception(exception)
  send(WrappedException.new(exception), sync: sync && :conclude)
end

#sync_after_receivingObject

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.



172
173
174
175
176
177
178
179
180
181
# File 'lib/ractor/server/request.rb', line 172

def sync_after_receiving
  # Only dynamic checks are done here; static validity checked in constructor
  case sync
  when :conclude, :interrupt
    Request.pending_receive_conclusion[response_to] = false
    Request.pending_send_conclusion[response_to.response_to] = false if sync == :interrupt
  when :ask, :converse
    Request.pending_send_conclusion[self] = true
  end
end

#to_procObject



34
35
36
# File 'lib/ractor/server/request.rb', line 34

def to_proc
  method(:===).to_proc
end