fleck 2.2.1 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/examples/expired.rb CHANGED
@@ -1,72 +1,72 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'fleck'
5
-
6
- user = ENV['USER'] || 'guest'
7
- pass = ENV['PASS'] || 'guest'
8
-
9
- CONCURRENCY = (ENV['CONCURRENCY'] || 2).to_i
10
- SAMPLES = (ENV['SAMPLES'] || 10).to_i
11
- QUEUE = 'expiration.example.queue'
12
-
13
- Fleck.configure do |config|
14
- config.default_user = user
15
- config.default_pass = pass
16
- config.loglevel = Logger::DEBUG
17
- end
18
-
19
- connection = Fleck.connection(host: '127.0.0.1', port: 5672, user: user, pass: pass, vhost: '/')
20
- client = Fleck::Client.new(connection, QUEUE, concurrency: CONCURRENCY.to_i)
21
- success_probability = 0.8
22
-
23
- count = 0
24
- success = 0
25
- failure = 0
26
-
27
- mutex = Mutex.new
28
- lock = Mutex.new
29
- condition = ConditionVariable.new
30
-
31
- class MyConsumer < Fleck::Consumer
32
- configure queue: QUEUE, concurrency: CONCURRENCY.to_i
33
-
34
- action :hello
35
- def hello
36
- sleep rand
37
- ok! "#{params[:num] + 1}. Hello!"
38
- end
39
- end
40
-
41
- SAMPLES.to_i.times do |num|
42
- client.request(
43
- action: 'hello',
44
- params: { num: num },
45
- async: true,
46
- timeout: (success_probability * SAMPLES.to_f) / CONCURRENCY
47
- ) do |request, response|
48
- if request.expired?
49
- puts "EXPIRED: #{response.inspect}"
50
- elsif response.status == 200
51
- puts "SUCCESS: #{response.body}"
52
- else
53
- puts "ERROR: #{response.inspect}"
54
- end
55
-
56
- mutex.synchronize do
57
- count += 1
58
- if response.status == 200
59
- success += 1
60
- else
61
- failure += 1
62
- end
63
-
64
- lock.synchronize { condition.signal } if count >= SAMPLES
65
- end
66
- end
67
- end
68
-
69
- lock.synchronize { condition.wait(lock) }
70
-
71
- puts "Ztimer: (count: #{Ztimer.count}, jobs: #{Ztimer.jobs_count})"
72
- puts "Total: #{count}, Success: #{success}, Failure: #{failure}"
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fleck'
5
+
6
+ user = ENV['USER'] || 'guest'
7
+ pass = ENV['PASS'] || 'guest'
8
+
9
+ CONCURRENCY = (ENV['CONCURRENCY'] || 2).to_i
10
+ SAMPLES = (ENV['SAMPLES'] || 10).to_i
11
+ QUEUE = 'expiration.example.queue'
12
+
13
+ Fleck.configure do |config|
14
+ config.default_user = user
15
+ config.default_pass = pass
16
+ config.loglevel = Logger::DEBUG
17
+ end
18
+
19
+ connection = Fleck.connection(host: '127.0.0.1', port: 5672, user: user, pass: pass, vhost: '/')
20
+ client = Fleck::Client.new(connection, QUEUE, concurrency: CONCURRENCY.to_i)
21
+ success_probability = 0.8
22
+
23
+ count = 0
24
+ success = 0
25
+ failure = 0
26
+
27
+ mutex = Mutex.new
28
+ lock = Mutex.new
29
+ condition = ConditionVariable.new
30
+
31
+ class MyConsumer < Fleck::Consumer
32
+ configure queue: QUEUE, concurrency: CONCURRENCY.to_i
33
+
34
+ action :hello
35
+ def hello
36
+ sleep rand
37
+ ok! "#{params[:num] + 1}. Hello!"
38
+ end
39
+ end
40
+
41
+ SAMPLES.to_i.times do |num|
42
+ client.request(
43
+ action: 'hello',
44
+ params: { num: num },
45
+ async: true,
46
+ timeout: (success_probability * SAMPLES.to_f) / CONCURRENCY
47
+ ) do |request, response|
48
+ if request.expired?
49
+ puts "EXPIRED: #{response.inspect}"
50
+ elsif response.status == 200
51
+ puts "SUCCESS: #{response.body}"
52
+ else
53
+ puts "ERROR: #{response.inspect}"
54
+ end
55
+
56
+ mutex.synchronize do
57
+ count += 1
58
+ if response.status == 200
59
+ success += 1
60
+ else
61
+ failure += 1
62
+ end
63
+
64
+ lock.synchronize { condition.signal } if count >= SAMPLES
65
+ end
66
+ end
67
+ end
68
+
69
+ lock.synchronize { condition.wait(lock) }
70
+
71
+ puts "Ztimer: (count: #{Ztimer.count}, jobs: #{Ztimer.jobs_count})"
72
+ puts "Total: #{count}, Success: #{success}, Failure: #{failure}"
data/examples/fanout.rb CHANGED
@@ -1,62 +1,62 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- require 'fleck'
5
-
6
- user = ENV['USER'] || 'guest'
7
- pass = ENV['PASS'] || 'guest'
8
-
9
- CONCURRENCY = (ENV['CONCURRENCY'] || 10).to_i
10
- SAMPLES = (ENV['SAMPLES'] || 1_000).to_i
11
-
12
- Fleck.configure do |config|
13
- config.default_user = user
14
- config.default_pass = pass
15
- config.loglevel = Logger::DEBUG
16
- end
17
-
18
- connection = Fleck.connection(host: "127.0.0.1", port: 5672, user: user, pass: pass, vhost: "/")
19
- client = Fleck::Client.new(connection, "example.queue", concurrency: CONCURRENCY.to_i, exchange_type: :fanout, exchange_name: 'fanout.example.queue', multiple_responses: true)
20
-
21
- count = 0
22
- success = 0
23
- failure = 0
24
-
25
- mutex = Mutex.new
26
- lock = Mutex.new
27
- condition = ConditionVariable.new
28
-
29
- class First < Fleck::Consumer
30
- configure queue: "example.queue", concurrency: CONCURRENCY.to_i, exchange_type: :fanout, exchange_name: 'fanout.example.queue'
31
-
32
- action :incr
33
- def incr
34
- if request.action == 'incr'
35
- ok! "#{request.params[:num].to_i + 1}. Hello, World!"
36
- else
37
- not_found!
38
- end
39
- end
40
- end
41
-
42
- Thread.new do
43
- SAMPLES.times do |i|
44
- client.request(action: 'incr', params: { num: i }, timeout: 60) do |request, response|
45
- request.logger.debug response.body
46
- mutex.synchronize do
47
- count += 1
48
- if response.status == 200
49
- success += 1
50
- else
51
- failure += 1
52
- end
53
-
54
- lock.synchronize { condition.signal } if count >= SAMPLES
55
- end
56
- end
57
- end
58
- end
59
-
60
- lock.synchronize { condition.wait(lock) }
61
-
62
- puts "Total: #{count}, Success: #{success}, Failure: #{failure}"
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'fleck'
5
+
6
+ user = ENV['USER'] || 'guest'
7
+ pass = ENV['PASS'] || 'guest'
8
+
9
+ CONCURRENCY = (ENV['CONCURRENCY'] || 10).to_i
10
+ SAMPLES = (ENV['SAMPLES'] || 1_000).to_i
11
+
12
+ Fleck.configure do |config|
13
+ config.default_user = user
14
+ config.default_pass = pass
15
+ config.loglevel = Logger::DEBUG
16
+ end
17
+
18
+ connection = Fleck.connection(host: "127.0.0.1", port: 5672, user: user, pass: pass, vhost: "/")
19
+ client = Fleck::Client.new(connection, "example.queue", concurrency: CONCURRENCY.to_i, exchange_type: :fanout, exchange_name: 'fanout.example.queue', multiple_responses: true)
20
+
21
+ count = 0
22
+ success = 0
23
+ failure = 0
24
+
25
+ mutex = Mutex.new
26
+ lock = Mutex.new
27
+ condition = ConditionVariable.new
28
+
29
+ class First < Fleck::Consumer
30
+ configure queue: "example.queue", concurrency: CONCURRENCY.to_i, exchange_type: :fanout, exchange_name: 'fanout.example.queue'
31
+
32
+ action :incr
33
+ def incr
34
+ if request.action == 'incr'
35
+ ok! "#{request.params[:num].to_i + 1}. Hello, World!"
36
+ else
37
+ not_found!
38
+ end
39
+ end
40
+ end
41
+
42
+ Thread.new do
43
+ SAMPLES.times do |i|
44
+ client.request(action: 'incr', params: { num: i }, timeout: 60) do |request, response|
45
+ request.logger.debug response.body
46
+ mutex.synchronize do
47
+ count += 1
48
+ if response.status == 200
49
+ success += 1
50
+ else
51
+ failure += 1
52
+ end
53
+
54
+ lock.synchronize { condition.signal } if count >= SAMPLES
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ lock.synchronize { condition.wait(lock) }
61
+
62
+ puts "Total: #{count}, Success: #{success}, Failure: #{failure}"
data/lib/fleck/client.rb CHANGED
@@ -1,124 +1,147 @@
1
-
2
- module Fleck
3
- class Client
4
- include Fleck::Loggable
5
-
6
- attr_reader :local_ip, :remote_ip
7
-
8
- def initialize(connection, queue_name = "", exchange_type: :direct, exchange_name: "", multiple_responses: false, concurrency: 1)
9
- @connection = connection
10
- @queue_name = queue_name
11
- @multiple_responses = multiple_responses
12
- @default_timeout = multiple_responses ? 60 : nil
13
- @concurrency = [concurrency.to_i, 1].max
14
- @requests = ThreadSafe::Hash.new
15
- @subscriptions = ThreadSafe::Array.new
16
- @terminated = false
17
- @mutex = Mutex.new
18
- @local_ip = @connection.transport.socket.local_address.ip_address
19
- @remote_ip = @connection.transport.socket.remote_address.ip_address
20
-
21
- @channel = @connection.create_channel
22
- @exchange = Bunny::Exchange.new(@channel, :direct, 'fleck')
23
- @publisher = Bunny::Exchange.new(@connection.create_channel, exchange_type, exchange_name)
24
- @reply_queue = @channel.queue("", exclusive: true, auto_delete: true)
25
- @reply_queue.bind(@exchange, routing_key: @reply_queue.name)
26
-
27
- handle_returned_messages!
28
- @concurrency.times { handle_responses! }
29
-
30
- logger.debug("Client initialized!")
31
-
32
- at_exit do
33
- terminate
34
- end
35
- end
36
-
37
- def request(action: nil, version: nil, headers: {}, params: {}, async: @multiple_responses || false, timeout: @default_timeout, queue: @queue_name, rmq_options: {}, &block)
38
-
39
- if @terminated
40
- return Fleck::Client::Response.new(Oj.dump({status: 503, errors: ['Service Unavailable'], body: nil} , mode: :compat))
41
- end
42
-
43
- request = Fleck::Client::Request.new(
44
- self, queue, @reply_queue.name,
45
- action: action,
46
- version: version,
47
- headers: headers,
48
- params: params,
49
- timeout: timeout,
50
- multiple_responses: @multiple_responses,
51
- rmq_options: rmq_options,
52
- &block
53
- )
54
-
55
- @requests[request.id] = request
56
- request.send!(async)
57
-
58
- return request.response
59
- end
60
-
61
-
62
- def publish(data, options)
63
- return if @terminated
64
- @mutex.synchronize { @publisher.publish(data, options) }
65
- end
66
-
67
-
68
- def remove_request(request_id)
69
- @requests.delete request_id
70
- end
71
-
72
-
73
- def terminate
74
- @terminated = true
75
- logger.info "Unsubscribing from #{@reply_queue.name}"
76
- @subscriptions.map(&:cancel) # stop receiving new messages
77
- logger.info "Canceling pending requests"
78
- # cancel pending requests
79
- while item = @requests.shift do
80
- begin
81
- item[1].cancel!
82
- rescue => e
83
- logger.error e.inspect + "\n" + e.backtrace.join("\n")
84
- end
85
- end
86
- end
87
-
88
-
89
- protected
90
-
91
- def handle_returned_messages!
92
- @exchange.on_return do |return_info, metadata, content|
93
- begin
94
- logger.warn "Request #{metadata[:correlation_id]} returned"
95
- request = @requests[metadata[:correlation_id]]
96
- if request
97
- request.cancel!
98
- end
99
- rescue => e
100
- logger.error e.inspect + "\n" + e.backtrace.join("\n")
101
- end
102
- end
103
- end
104
-
105
- def handle_responses!
106
- @subscriptions << @reply_queue.subscribe do |delivery_info, metadata, payload|
107
- begin
108
- logger.debug "Response received: #{payload}"
109
- request = @requests[metadata[:correlation_id]]
110
- if request
111
- request.response = Fleck::Client::Response.new(payload)
112
- else
113
- logger.warn "Request #{metadata[:correlation_id]} not found!"
114
- end
115
- rescue => e
116
- logger.error e.inspect + "\n" + e.backtrace.join("\n")
117
- end
118
- end
119
- end
120
- end
121
- end
122
-
123
- require "fleck/client/request"
124
- require "fleck/client/response"
1
+
2
+ module Fleck
3
+ class Client
4
+ include Fleck::Loggable
5
+
6
+ @instances = ThreadSafe::Array.new
7
+
8
+ def self.<<(new_instance)
9
+ @instances << new_instance
10
+ end
11
+
12
+ def self.remove_instance(instance)
13
+ @instances.delete(instance)
14
+ end
15
+
16
+ def self.terminate_all
17
+ @instances.map(&:terminate)
18
+ end
19
+
20
+ attr_reader :local_ip, :remote_ip, :terminated
21
+
22
+ def initialize(connection, queue_name = "", exchange_type: :direct, exchange_name: "", multiple_responses: false, concurrency: 1)
23
+ @connection = connection
24
+ @queue_name = queue_name
25
+ @multiple_responses = multiple_responses
26
+ @default_timeout = multiple_responses ? 60 : nil
27
+ @concurrency = [concurrency.to_i, 1].max
28
+ @requests = ThreadSafe::Hash.new
29
+ @subscriptions = ThreadSafe::Array.new
30
+ @terminated = false
31
+ @mutex = Mutex.new
32
+ @local_ip = @connection.transport.socket.local_address.ip_address
33
+ @remote_ip = @connection.transport.socket.remote_address.ip_address
34
+
35
+ @channel = @connection.create_channel
36
+ @exchange = Bunny::Exchange.new(@channel, :direct, 'fleck')
37
+ @publisher = Bunny::Exchange.new(@connection.create_channel, exchange_type, exchange_name)
38
+ @reply_queue = @channel.queue("", exclusive: true, auto_delete: true)
39
+ @reply_queue.bind(@exchange, routing_key: @reply_queue.name)
40
+
41
+ handle_returned_messages!
42
+ @concurrency.times { handle_responses! }
43
+
44
+ logger.debug("Client initialized!")
45
+
46
+ Fleck::Client << self
47
+
48
+ # at_exit do
49
+ # terminate
50
+ # end
51
+ end
52
+
53
+ def request(action: nil, version: nil, headers: {}, params: {}, async: @multiple_responses || false, timeout: @default_timeout, queue: @queue_name, rmq_options: {}, &block)
54
+
55
+ if @terminated
56
+ return Fleck::Client::Response.new(Oj.dump({status: 503, errors: ['Service Unavailable'], body: nil} , mode: :compat))
57
+ end
58
+
59
+ request = Fleck::Client::Request.new(
60
+ self, queue, @reply_queue.name,
61
+ action: action,
62
+ version: version,
63
+ headers: headers,
64
+ params: params,
65
+ timeout: timeout,
66
+ multiple_responses: @multiple_responses,
67
+ rmq_options: rmq_options,
68
+ &block
69
+ )
70
+
71
+ @requests[request.id] = request
72
+ request.send!(async)
73
+
74
+ return request.response
75
+ end
76
+
77
+
78
+ def publish(data, options)
79
+ return if @terminated
80
+ @mutex.synchronize { @publisher.publish(data, options) }
81
+ end
82
+
83
+
84
+ def remove_request(request_id)
85
+ @requests.delete request_id
86
+ end
87
+
88
+
89
+ def terminate
90
+ @terminated = true
91
+ logger.info "Unsubscribing from #{@reply_queue.name}"
92
+ # @subscriptions.map(&:cancel) # stop receiving new messages
93
+ @channel&.close unless @channel&.closed?
94
+ logger.info "Canceling pending requests"
95
+ # cancel pending requests
96
+ while item = @requests.shift do
97
+ begin
98
+ item[1].cancel!
99
+ rescue => e
100
+ logger.error e.inspect + "\n" + e.backtrace.join("\n")
101
+ end
102
+ end
103
+
104
+ Fleck::Client.remove_instance(self)
105
+ end
106
+
107
+
108
+ protected
109
+
110
+ def handle_returned_messages!
111
+ @exchange.on_return do |return_info, metadata, content|
112
+ begin
113
+ logger.warn "Request #{metadata[:correlation_id]} returned"
114
+ request = @requests[metadata[:correlation_id]]
115
+ if request
116
+ request.cancel!
117
+ end
118
+ rescue => e
119
+ logger.error e.inspect + "\n" + e.backtrace.join("\n")
120
+ end
121
+ end
122
+ end
123
+
124
+ def handle_responses!
125
+ @subscriptions << @reply_queue.subscribe do |delivery_info, metadata, payload|
126
+ begin
127
+ logger.debug "Response received: #{payload}"
128
+ request = @requests[metadata[:correlation_id]]
129
+ if request
130
+ request.response = Fleck::Client::Response.new(payload)
131
+ else
132
+ logger.warn "Request #{metadata[:correlation_id]} not found!"
133
+ end
134
+ rescue => e
135
+ logger.error e.inspect + "\n" + e.backtrace.join("\n")
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+
142
+ at_exit do
143
+ Fleck::Client.terminate_all
144
+ end
145
+
146
+ require 'fleck/client/request'
147
+ require 'fleck/client/response'