falqon 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -10
- data/Gemfile +6 -6
- data/README.md +4 -3
- data/lib/falqon/message.rb +21 -20
- data/lib/falqon/queue.rb +45 -31
- data/lib/falqon/strategies/linear.rb +7 -7
- data/lib/falqon/strategies/none.rb +7 -7
- data/lib/falqon/sub_queue.rb +1 -0
- data/lib/falqon/sub_set.rb +1 -0
- data/lib/falqon/version.rb +2 -2
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a6de2c2359a6d2aebf3f7f0531b9dea885d46f579a64aa0b46036c204c7df52
|
4
|
+
data.tar.gz: 8896a1d994cd209f436c8c260c5eba7985c9b3055064f186e26d7ff8452f7407
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 465c3dc7415da3ee83118227916a0d21a653fd8c74b2876a73e2510e545e7b210d0a96425d3f014ad997516f9314fea9de819b81deb373ec949162a3b7d6ca15
|
7
|
+
data.tar.gz: 231afe294759e0cc1fe0b0a884a99044808021e0d6d1f7201a8406f7a5b0b0128c6821f25b6d743d9c2475e9397c94dce10fc12ec831fbd123c7875495e067a1
|
data/CHANGELOG.md
CHANGED
@@ -1,13 +1,5 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## Falqon v0.1.0 (2024-11-16)
|
4
|
-
|
5
|
-
Initial release
|
6
|
-
|
7
|
-
## Falqon v0.0.1 (2023-06-22)
|
8
|
-
|
9
|
-
# Changelog
|
10
|
-
|
11
3
|
All notable changes to this project will be documented in this file.
|
12
4
|
|
13
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
@@ -21,5 +13,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
21
13
|
|
22
14
|
### Removed
|
23
15
|
|
24
|
-
|
25
|
-
|
16
|
+
## Falqon v1.0.0 (2024-12-07)
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
|
20
|
+
- Use atomic execution (MULTI/EXEC) where possible.
|
21
|
+
|
22
|
+
## Falqon v0.1.0 (2024-11-16)
|
23
|
+
|
24
|
+
Initial release
|
25
|
+
|
26
|
+
## Falqon v0.0.1 (2023-06-22)
|
27
|
+
|
28
|
+
[unreleased]: https://github.com/floriandejonckheere/falqon/compare/v1.0.0...HEAD
|
29
|
+
[1.0.0]: https://github.com/floriandejonckheere/falqon-pro/releases/tag/v1.0.0
|
30
|
+
[0.1.0]: https://github.com/floriandejonckheere/falqon-pro/releases/tag/v0.1.0
|
data/Gemfile
CHANGED
@@ -14,7 +14,7 @@ group :development do
|
|
14
14
|
gem "yard-sorbet", "0.9.0", require: false
|
15
15
|
|
16
16
|
# Simple server
|
17
|
-
gem "webrick", "1.
|
17
|
+
gem "webrick", "1.9.1", require: false
|
18
18
|
end
|
19
19
|
|
20
20
|
group :development, :test do
|
@@ -28,21 +28,21 @@ group :development, :test do
|
|
28
28
|
gem "ffaker", "2.23.0", require: false
|
29
29
|
|
30
30
|
# Mock Redis server
|
31
|
-
gem "mock_redis", "0.
|
31
|
+
gem "mock_redis", "0.48.1", require: false
|
32
32
|
|
33
33
|
# Behavior-driven test framework
|
34
34
|
gem "rspec", "3.13.0", require: false
|
35
35
|
|
36
36
|
# Linter
|
37
|
-
gem "rubocop", "1.
|
37
|
+
gem "rubocop", "1.69.0", require: false
|
38
38
|
gem "rubocop-factory_bot", "2.26.1", require: false
|
39
|
-
gem "rubocop-performance", "1.
|
39
|
+
gem "rubocop-performance", "1.23.0", require: false
|
40
40
|
gem "rubocop-rake", "0.6.0", require: false
|
41
41
|
gem "rubocop-rspec", "3.2.0", require: false
|
42
42
|
|
43
43
|
# Type checker
|
44
|
-
gem "sorbet", "0.5.
|
45
|
-
gem "tapioca", "0.16.
|
44
|
+
gem "sorbet", "0.5.11672", require: false
|
45
|
+
gem "tapioca", "0.16.5", require: false
|
46
46
|
|
47
47
|
# Time control
|
48
48
|
gem "timecop", "0.9.10", require: false
|
data/README.md
CHANGED
@@ -23,8 +23,9 @@ Falqon offers an elegant solution for messaging queues in Ruby.
|
|
23
23
|
|
24
24
|
- Install Falqon and get working with messaging queues in a heartbeat using the [quickstart guide](#quickstart)
|
25
25
|
- Check out the [API documentation](https://docs.falqon.dev/) for more information on how to use Falqon in your application
|
26
|
-
- Check out the CLI documentation](https://docs.falqon.dev/) for more information on how to manage queues and messages from the command line
|
26
|
+
- Check out the [CLI documentation](https://docs.falqon.dev/Falqon/CLI.html) for more information on how to manage queues and messages from the command line
|
27
27
|
- Read the [architecture documentation](#architecture) to learn more about how Falqon works under the hood
|
28
|
+
- Read about [Falqon Pro](https://docs.falqon.dev/pro), the commercial addon for Falqon that offers additional features
|
28
29
|
|
29
30
|
## Quickstart
|
30
31
|
|
@@ -52,7 +53,7 @@ Or install it yourself as:
|
|
52
53
|
### Configuration
|
53
54
|
|
54
55
|
The default configuration works out of the box with the provided `docker-compose.yml` file.
|
55
|
-
See [configuration](
|
56
|
+
See [configuration](https://docs.falqon.dev/Falqon/Configuration.html) if you want to adjust the configuration.
|
56
57
|
|
57
58
|
### Usage
|
58
59
|
|
@@ -134,7 +135,7 @@ The documentation in `docs/` is automatically built by [YARD](https://yardoc.org
|
|
134
135
|
Locally, you can build the documentation using the following commands:
|
135
136
|
|
136
137
|
```sh
|
137
|
-
rake
|
138
|
+
rake yard
|
138
139
|
```
|
139
140
|
|
140
141
|
In development, you can start a local server to preview the documentation:
|
data/lib/falqon/message.rb
CHANGED
@@ -101,13 +101,17 @@ module Falqon
|
|
101
101
|
sig { returns(Message) }
|
102
102
|
def create
|
103
103
|
redis.with do |r|
|
104
|
-
|
105
|
-
r.set("#{queue.id}:data:#{id}", data)
|
104
|
+
message_id = id
|
106
105
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
106
|
+
r.multi do |t|
|
107
|
+
# Store data
|
108
|
+
t.set("#{queue.id}:data:#{message_id}", data)
|
109
|
+
|
110
|
+
# Set metadata
|
111
|
+
t.hset("#{queue.id}:metadata:#{message_id}",
|
112
|
+
:created_at, Time.now.to_i,
|
113
|
+
:updated_at, Time.now.to_i,)
|
114
|
+
end
|
111
115
|
end
|
112
116
|
|
113
117
|
self
|
@@ -141,12 +145,14 @@ module Falqon
|
|
141
145
|
sig { void }
|
142
146
|
def delete
|
143
147
|
redis.with do |r|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
148
|
+
r.multi do |t|
|
149
|
+
# Delete message from queue
|
150
|
+
queue.pending.remove(id)
|
151
|
+
queue.dead.remove(id)
|
152
|
+
|
153
|
+
# Delete data and metadata
|
154
|
+
t.del("#{queue.id}:data:#{id}", "#{queue.id}:metadata:#{id}")
|
155
|
+
end
|
150
156
|
end
|
151
157
|
end
|
152
158
|
|
@@ -156,9 +162,7 @@ module Falqon
|
|
156
162
|
#
|
157
163
|
sig { returns Integer }
|
158
164
|
def size
|
159
|
-
redis.with
|
160
|
-
r.strlen("#{queue.id}:data:#{id}")
|
161
|
-
end
|
165
|
+
redis.with { |r| r.strlen("#{queue.id}:data:#{id}") }
|
162
166
|
end
|
163
167
|
|
164
168
|
# Metadata of the message
|
@@ -183,7 +187,7 @@ module Falqon
|
|
183
187
|
def_delegator :queue, :logger
|
184
188
|
|
185
189
|
##
|
186
|
-
# Metadata for
|
190
|
+
# Metadata for a message
|
187
191
|
#
|
188
192
|
class Metadata < T::Struct
|
189
193
|
# Status (unknown, pending, processing, scheduled, dead)
|
@@ -209,11 +213,8 @@ module Falqon
|
|
209
213
|
# @!visibility private
|
210
214
|
#
|
211
215
|
def self.parse(data)
|
212
|
-
# Keys that are not numeric
|
213
|
-
keys = ["status", "retry_error"]
|
214
|
-
|
215
216
|
# Transform keys to symbols, and values to integers
|
216
|
-
new(data.to_h { |k, v| [k.to_sym,
|
217
|
+
new(data.to_h { |k, v| [k.to_sym, (send(props.dig(k.to_sym, :type).name.to_sym, v) if v)] })
|
217
218
|
end
|
218
219
|
end
|
219
220
|
end
|
data/lib/falqon/queue.rb
CHANGED
@@ -91,15 +91,17 @@ module Falqon
|
|
91
91
|
|
92
92
|
raise Falqon::VersionMismatchError, "Queue #{name} is using protocol version #{queue_version}, but this client is using protocol version #{version}" if queue_version && queue_version.to_i != @version
|
93
93
|
|
94
|
-
|
95
|
-
|
94
|
+
r.multi do |t|
|
95
|
+
# Register the queue
|
96
|
+
t.sadd([Falqon.configuration.prefix, "queues"].compact.join(":"), name)
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
98
|
+
# Set creation and update timestamp (if not set)
|
99
|
+
t.hsetnx("#{id}:metadata", :created_at, Time.now.to_i)
|
100
|
+
t.hsetnx("#{id}:metadata", :updated_at, Time.now.to_i)
|
100
101
|
|
101
|
-
|
102
|
-
|
102
|
+
# Set protocol version
|
103
|
+
t.hsetnx("#{id}:metadata", :version, @version)
|
104
|
+
end
|
103
105
|
end
|
104
106
|
|
105
107
|
run_hook :initialize, :after
|
@@ -185,18 +187,23 @@ module Falqon
|
|
185
187
|
# Move identifier from pending queue to processing queue
|
186
188
|
message_id = r.blmove(pending.id, processing.id, :left, :right).to_i
|
187
189
|
|
188
|
-
#
|
189
|
-
r.
|
190
|
+
# Get retry count
|
191
|
+
retries = r.hget("#{id}:metadata:#{message_id}", :retries).to_i
|
190
192
|
|
191
|
-
|
192
|
-
|
193
|
-
|
193
|
+
r.multi do |t|
|
194
|
+
# Set message status
|
195
|
+
t.hset("#{id}:metadata:#{message_id}", :status, "processing")
|
194
196
|
|
195
|
-
|
196
|
-
|
197
|
+
# Set update timestamp
|
198
|
+
t.hset("#{id}:metadata", :updated_at, Time.now.to_i)
|
199
|
+
t.hset("#{id}:metadata:#{message_id}", :updated_at, Time.now.to_i)
|
197
200
|
|
198
|
-
|
199
|
-
|
201
|
+
# Increment processing counter
|
202
|
+
t.hincrby("#{id}:metadata", :processed, 1)
|
203
|
+
|
204
|
+
# Increment retry counter if message is retried
|
205
|
+
t.hincrby("#{id}:metadata", :retried, 1) if retries.positive?
|
206
|
+
end
|
200
207
|
|
201
208
|
Message.new(self, id: message_id)
|
202
209
|
end
|
@@ -318,11 +325,13 @@ module Falqon
|
|
318
325
|
message_ids = pending.clear + processing.clear + scheduled.clear + dead.clear
|
319
326
|
|
320
327
|
redis.with do |r|
|
321
|
-
|
322
|
-
|
328
|
+
r.multi do |t|
|
329
|
+
# Clear metadata
|
330
|
+
t.hdel("#{id}:metadata", :processed, :failed, :retried)
|
323
331
|
|
324
|
-
|
325
|
-
|
332
|
+
# Set update timestamp
|
333
|
+
t.hset("#{id}:metadata", :updated_at, Time.now.to_i)
|
334
|
+
end
|
326
335
|
end
|
327
336
|
|
328
337
|
run_hook :clear, :after
|
@@ -351,11 +360,13 @@ module Falqon
|
|
351
360
|
.each(&:clear)
|
352
361
|
|
353
362
|
redis.with do |r|
|
354
|
-
|
355
|
-
|
363
|
+
r.multi do |t|
|
364
|
+
# Delete metadata
|
365
|
+
t.del("#{id}:metadata")
|
356
366
|
|
357
|
-
|
358
|
-
|
367
|
+
# Deregister the queue
|
368
|
+
t.srem([Falqon.configuration.prefix, "queues"].compact.join(":"), name)
|
369
|
+
end
|
359
370
|
end
|
360
371
|
|
361
372
|
run_hook :delete, :after
|
@@ -461,19 +472,22 @@ module Falqon
|
|
461
472
|
redis.with do |r|
|
462
473
|
# Select all identifiers that are due (score <= current timestamp)
|
463
474
|
# FIXME: replace with zrange(by_score: true) when https://github.com/sds/mock_redis/issues/307 is resolved
|
475
|
+
# TODO: work in batches
|
464
476
|
message_ids = r.zrangebyscore(scheduled.id, 0, Time.now.to_i).map(&:to_i)
|
465
477
|
|
466
478
|
logger.debug "Scheduling messages #{message_ids.join(', ')} on queue #{name}"
|
467
479
|
|
468
|
-
|
469
|
-
|
470
|
-
|
480
|
+
r.multi do |t|
|
481
|
+
message_ids.each do |message_id|
|
482
|
+
# Set message status
|
483
|
+
t.hset("#{id}:metadata:#{message_id}", :status, "pending")
|
471
484
|
|
472
|
-
|
473
|
-
|
485
|
+
# Add identifier to pending queue
|
486
|
+
pending.add(message_id)
|
474
487
|
|
475
|
-
|
476
|
-
|
488
|
+
# Remove identifier from scheduled queue
|
489
|
+
scheduled.remove(message_id)
|
490
|
+
end
|
477
491
|
end
|
478
492
|
end
|
479
493
|
|
@@ -38,14 +38,14 @@ module Falqon
|
|
38
38
|
# Increment retry count
|
39
39
|
retries = r.hincrby("#{queue.id}:metadata:#{message.id}", :retries, 1)
|
40
40
|
|
41
|
-
# Set error metadata
|
42
|
-
r.hset(
|
43
|
-
"#{queue.id}:metadata:#{message.id}",
|
44
|
-
:retried_at, Time.now.to_i,
|
45
|
-
:retry_error, error.message,
|
46
|
-
)
|
47
|
-
|
48
41
|
r.multi do |t|
|
42
|
+
# Set error metadata
|
43
|
+
t.hset(
|
44
|
+
"#{queue.id}:metadata:#{message.id}",
|
45
|
+
:retried_at, Time.now.to_i,
|
46
|
+
:retry_error, error.message,
|
47
|
+
)
|
48
|
+
|
49
49
|
if retries < queue.max_retries || queue.max_retries == -1
|
50
50
|
if queue.retry_delay.positive?
|
51
51
|
queue.logger.debug "Scheduling message #{message.id} on queue #{queue.name} in #{queue.retry_delay} seconds (attempt #{retries})"
|
@@ -20,14 +20,14 @@ module Falqon
|
|
20
20
|
sig { params(message: Message, error: Error).void }
|
21
21
|
def retry(message, error)
|
22
22
|
queue.redis.with do |r|
|
23
|
-
# Set error metadata
|
24
|
-
r.hset(
|
25
|
-
"#{queue.id}:metadata:#{message.id}",
|
26
|
-
:retried_at, Time.now.to_i,
|
27
|
-
:retry_error, error.message,
|
28
|
-
)
|
29
|
-
|
30
23
|
r.multi do |t|
|
24
|
+
# Set error metadata
|
25
|
+
t.hset(
|
26
|
+
"#{queue.id}:metadata:#{message.id}",
|
27
|
+
:retried_at, Time.now.to_i,
|
28
|
+
:retry_error, error.message,
|
29
|
+
)
|
30
|
+
|
31
31
|
# Kill message immediately
|
32
32
|
message.kill
|
33
33
|
|
data/lib/falqon/sub_queue.rb
CHANGED
@@ -65,6 +65,7 @@ module Falqon
|
|
65
65
|
message_ids = r.lrange(id, 0, -1)
|
66
66
|
|
67
67
|
# Delete all data and clear queue
|
68
|
+
# TODO: clear data in batches
|
68
69
|
r.del(*message_ids.flat_map { |message_id| ["#{queue.id}:data:#{message_id}", "#{queue.id}:metadata:#{message_id}"] }, id, "#{queue.id}:id")
|
69
70
|
|
70
71
|
# Return identifiers
|
data/lib/falqon/sub_set.rb
CHANGED
data/lib/falqon/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: falqon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Florian Dejonckheere
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: connection_pool
|
@@ -130,7 +130,7 @@ licenses:
|
|
130
130
|
metadata:
|
131
131
|
source_code_uri: https://github.com/floriandejonckheere/falqon.git
|
132
132
|
rubygems_mfa_required: 'true'
|
133
|
-
post_install_message:
|
133
|
+
post_install_message:
|
134
134
|
rdoc_options: []
|
135
135
|
require_paths:
|
136
136
|
- lib
|
@@ -145,8 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
requirements: []
|
148
|
-
rubygems_version: 3.
|
149
|
-
signing_key:
|
148
|
+
rubygems_version: 3.4.20
|
149
|
+
signing_key:
|
150
150
|
specification_version: 4
|
151
151
|
summary: Simple messaging queue
|
152
152
|
test_files: []
|