fila-client 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +661 -0
- data/README.md +93 -0
- data/lib/fila/client.rb +140 -0
- data/lib/fila/consume_message.rb +14 -0
- data/lib/fila/errors.rb +25 -0
- data/lib/fila/proto/fila/v1/admin_pb.rb +37 -0
- data/lib/fila/proto/fila/v1/admin_services_pb.rb +32 -0
- data/lib/fila/proto/fila/v1/messages_pb.rb +21 -0
- data/lib/fila/proto/fila/v1/service_pb.rb +26 -0
- data/lib/fila/proto/fila/v1/service_services_pb.rb +28 -0
- data/lib/fila/version.rb +5 -0
- data/lib/fila.rb +6 -0
- data/proto/fila/v1/admin.proto +114 -0
- data/proto/fila/v1/messages.proto +28 -0
- data/proto/fila/v1/service.proto +45 -0
- metadata +87 -0
data/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# fila-ruby
|
|
2
|
+
|
|
3
|
+
Ruby client SDK for the [Fila](https://github.com/faisca/fila) message broker.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
gem install fila-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or add to your Gemfile:
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
gem "fila-client"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
require "fila"
|
|
21
|
+
|
|
22
|
+
client = Fila::Client.new("localhost:5555")
|
|
23
|
+
|
|
24
|
+
# Enqueue a message.
|
|
25
|
+
msg_id = client.enqueue(
|
|
26
|
+
queue: "my-queue",
|
|
27
|
+
headers: { "tenant" => "acme" },
|
|
28
|
+
payload: "hello world"
|
|
29
|
+
)
|
|
30
|
+
puts "Enqueued: #{msg_id}"
|
|
31
|
+
|
|
32
|
+
# Consume messages (block form).
|
|
33
|
+
client.consume(queue: "my-queue") do |msg|
|
|
34
|
+
puts "Received: #{msg.id} (attempt #{msg.attempt_count})"
|
|
35
|
+
|
|
36
|
+
begin
|
|
37
|
+
# Process the message...
|
|
38
|
+
client.ack(queue: "my-queue", msg_id: msg.id)
|
|
39
|
+
rescue => e
|
|
40
|
+
client.nack(queue: "my-queue", msg_id: msg.id, error: e.message)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
client.close
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### `Fila::Client.new(addr)`
|
|
50
|
+
|
|
51
|
+
Connect to a Fila broker at the given address (e.g., `"localhost:5555"`).
|
|
52
|
+
|
|
53
|
+
### `client.enqueue(queue:, headers:, payload:)`
|
|
54
|
+
|
|
55
|
+
Enqueue a message. Returns the broker-assigned message ID (UUIDv7).
|
|
56
|
+
|
|
57
|
+
### `client.consume(queue:) { |msg| ... }`
|
|
58
|
+
|
|
59
|
+
Open a streaming consumer. Yields `Fila::ConsumeMessage` objects as they become available. If no block is given, returns an `Enumerator`. Nacked messages are redelivered on the same stream.
|
|
60
|
+
|
|
61
|
+
### `client.ack(queue:, msg_id:)`
|
|
62
|
+
|
|
63
|
+
Acknowledge a successfully processed message. The message is permanently removed.
|
|
64
|
+
|
|
65
|
+
### `client.nack(queue:, msg_id:, error:)`
|
|
66
|
+
|
|
67
|
+
Negatively acknowledge a failed message. The message is requeued or routed to the dead-letter queue based on the queue's configuration.
|
|
68
|
+
|
|
69
|
+
### `client.close`
|
|
70
|
+
|
|
71
|
+
Close the underlying gRPC channel.
|
|
72
|
+
|
|
73
|
+
## Error Handling
|
|
74
|
+
|
|
75
|
+
Per-operation error classes are raised for specific failure modes:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
begin
|
|
79
|
+
client.enqueue(queue: "missing-queue", payload: "test")
|
|
80
|
+
rescue Fila::QueueNotFoundError => e
|
|
81
|
+
# handle queue not found
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
begin
|
|
85
|
+
client.ack(queue: "my-queue", msg_id: "missing-id")
|
|
86
|
+
rescue Fila::MessageNotFoundError => e
|
|
87
|
+
# handle message not found
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## License
|
|
92
|
+
|
|
93
|
+
AGPLv3
|
data/lib/fila/client.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'grpc'
|
|
4
|
+
|
|
5
|
+
# Add proto directory to load path so generated requires resolve correctly.
|
|
6
|
+
$LOAD_PATH.unshift(File.expand_path('proto', __dir__)) unless $LOAD_PATH.include?(File.expand_path('proto', __dir__))
|
|
7
|
+
|
|
8
|
+
require_relative 'proto/fila/v1/service_services_pb'
|
|
9
|
+
require_relative 'errors'
|
|
10
|
+
require_relative 'consume_message'
|
|
11
|
+
|
|
12
|
+
module Fila
|
|
13
|
+
# Client for the Fila message broker.
|
|
14
|
+
#
|
|
15
|
+
# Wraps the hot-path gRPC operations: enqueue, consume, ack, nack.
|
|
16
|
+
#
|
|
17
|
+
# @example
|
|
18
|
+
# client = Fila::Client.new("localhost:5555")
|
|
19
|
+
# msg_id = client.enqueue(queue: "my-queue", headers: { "tenant" => "acme" }, payload: "hello")
|
|
20
|
+
# client.consume(queue: "my-queue") do |msg|
|
|
21
|
+
# client.ack(queue: "my-queue", msg_id: msg.id)
|
|
22
|
+
# break
|
|
23
|
+
# end
|
|
24
|
+
# client.close
|
|
25
|
+
class Client
|
|
26
|
+
# Connect to a Fila broker at the given address.
|
|
27
|
+
#
|
|
28
|
+
# @param addr [String] broker address in "host:port" format (e.g., "localhost:5555")
|
|
29
|
+
def initialize(addr)
|
|
30
|
+
@stub = ::Fila::V1::FilaService::Stub.new(addr, :this_channel_is_insecure)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Close the underlying gRPC channel.
|
|
34
|
+
def close
|
|
35
|
+
# grpc-ruby doesn't expose a direct channel close on stubs;
|
|
36
|
+
# the channel is garbage-collected. This is a no-op for API symmetry.
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Enqueue a message to the specified queue.
|
|
40
|
+
#
|
|
41
|
+
# @param queue [String] target queue name
|
|
42
|
+
# @param headers [Hash<String, String>, nil] optional message headers
|
|
43
|
+
# @param payload [String] message payload bytes
|
|
44
|
+
# @return [String] broker-assigned message ID (UUIDv7)
|
|
45
|
+
# @raise [QueueNotFoundError] if the queue does not exist
|
|
46
|
+
# @raise [RPCError] for unexpected gRPC failures
|
|
47
|
+
def enqueue(queue:, payload:, headers: nil)
|
|
48
|
+
req = ::Fila::V1::EnqueueRequest.new(
|
|
49
|
+
queue: queue,
|
|
50
|
+
headers: headers || {},
|
|
51
|
+
payload: payload
|
|
52
|
+
)
|
|
53
|
+
resp = @stub.enqueue(req)
|
|
54
|
+
resp.message_id
|
|
55
|
+
rescue GRPC::NotFound => e
|
|
56
|
+
raise QueueNotFoundError, "enqueue: #{e.details}"
|
|
57
|
+
rescue GRPC::BadStatus => e
|
|
58
|
+
raise RPCError.new(e.code, e.details)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Open a streaming consumer on the specified queue.
|
|
62
|
+
#
|
|
63
|
+
# Yields messages as they become available. Nil message frames (keepalive
|
|
64
|
+
# signals) are skipped automatically. Nacked messages are redelivered on
|
|
65
|
+
# the same stream.
|
|
66
|
+
#
|
|
67
|
+
# If no block is given, returns an Enumerator.
|
|
68
|
+
#
|
|
69
|
+
# @param queue [String] queue to consume from
|
|
70
|
+
# @yield [ConsumeMessage] each message received from the broker
|
|
71
|
+
# @return [Enumerator<ConsumeMessage>] if no block given
|
|
72
|
+
# @raise [QueueNotFoundError] if the queue does not exist
|
|
73
|
+
# @raise [RPCError] for unexpected gRPC failures
|
|
74
|
+
def consume(queue:, &block)
|
|
75
|
+
return enum_for(:consume, queue: queue) unless block
|
|
76
|
+
|
|
77
|
+
req = ::Fila::V1::ConsumeRequest.new(queue: queue)
|
|
78
|
+
stream = @stub.consume(req)
|
|
79
|
+
stream.each do |resp|
|
|
80
|
+
msg = resp.message
|
|
81
|
+
next if msg.nil? || msg.id.empty?
|
|
82
|
+
|
|
83
|
+
block.call(build_consume_message(msg))
|
|
84
|
+
end
|
|
85
|
+
rescue GRPC::Cancelled
|
|
86
|
+
# Stream cancelled — normal when consumer breaks out of the loop.
|
|
87
|
+
rescue GRPC::NotFound => e
|
|
88
|
+
raise QueueNotFoundError, "consume: #{e.details}"
|
|
89
|
+
rescue GRPC::BadStatus => e
|
|
90
|
+
raise RPCError.new(e.code, e.details)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Acknowledge a successfully processed message.
|
|
94
|
+
#
|
|
95
|
+
# @param queue [String] queue the message belongs to
|
|
96
|
+
# @param msg_id [String] ID of the message to acknowledge
|
|
97
|
+
# @raise [MessageNotFoundError] if the message does not exist
|
|
98
|
+
# @raise [RPCError] for unexpected gRPC failures
|
|
99
|
+
def ack(queue:, msg_id:)
|
|
100
|
+
req = ::Fila::V1::AckRequest.new(queue: queue, message_id: msg_id)
|
|
101
|
+
@stub.ack(req)
|
|
102
|
+
nil
|
|
103
|
+
rescue GRPC::NotFound => e
|
|
104
|
+
raise MessageNotFoundError, "ack: #{e.details}"
|
|
105
|
+
rescue GRPC::BadStatus => e
|
|
106
|
+
raise RPCError.new(e.code, e.details)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Negatively acknowledge a message that failed processing.
|
|
110
|
+
#
|
|
111
|
+
# @param queue [String] queue the message belongs to
|
|
112
|
+
# @param msg_id [String] ID of the message to nack
|
|
113
|
+
# @param error [String] description of the failure
|
|
114
|
+
# @raise [MessageNotFoundError] if the message does not exist
|
|
115
|
+
# @raise [RPCError] for unexpected gRPC failures
|
|
116
|
+
def nack(queue:, msg_id:, error:)
|
|
117
|
+
req = ::Fila::V1::NackRequest.new(queue: queue, message_id: msg_id, error: error)
|
|
118
|
+
@stub.nack(req)
|
|
119
|
+
nil
|
|
120
|
+
rescue GRPC::NotFound => e
|
|
121
|
+
raise MessageNotFoundError, "nack: #{e.details}"
|
|
122
|
+
rescue GRPC::BadStatus => e
|
|
123
|
+
raise RPCError.new(e.code, e.details)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def build_consume_message(msg)
|
|
129
|
+
metadata = msg.metadata
|
|
130
|
+
ConsumeMessage.new(
|
|
131
|
+
id: msg.id,
|
|
132
|
+
headers: msg.headers.to_h,
|
|
133
|
+
payload: msg.payload,
|
|
134
|
+
fairness_key: metadata&.fairness_key.to_s,
|
|
135
|
+
attempt_count: metadata&.attempt_count.to_i,
|
|
136
|
+
queue: metadata&.queue_id.to_s
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fila
|
|
4
|
+
# A message received from the broker via a consume stream.
|
|
5
|
+
ConsumeMessage = Struct.new(
|
|
6
|
+
:id, # Broker-assigned message ID (UUIDv7).
|
|
7
|
+
:headers, # Message headers (Hash<String, String>).
|
|
8
|
+
:payload, # Message payload bytes (String).
|
|
9
|
+
:fairness_key, # Fairness key for scheduling.
|
|
10
|
+
:attempt_count, # Number of previous delivery attempts.
|
|
11
|
+
:queue, # Queue the message belongs to.
|
|
12
|
+
keyword_init: true
|
|
13
|
+
)
|
|
14
|
+
end
|
data/lib/fila/errors.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Fila
|
|
4
|
+
# Base error for all Fila SDK errors.
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
# Raised when the specified queue does not exist.
|
|
8
|
+
class QueueNotFoundError < Error; end
|
|
9
|
+
|
|
10
|
+
# Raised when the specified message does not exist.
|
|
11
|
+
class MessageNotFoundError < Error; end
|
|
12
|
+
|
|
13
|
+
# Raised for unexpected gRPC failures, preserving status code and message.
|
|
14
|
+
class RPCError < Error
|
|
15
|
+
# @return [Integer] gRPC status code
|
|
16
|
+
attr_reader :code
|
|
17
|
+
|
|
18
|
+
# @param code [Integer] gRPC status code
|
|
19
|
+
# @param message [String] error message
|
|
20
|
+
def initialize(code, message)
|
|
21
|
+
@code = code
|
|
22
|
+
super("rpc error (code = #{code}): #{message}")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: fila/v1/admin.proto
|
|
4
|
+
|
|
5
|
+
require 'google/protobuf'
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
descriptor_data = "\n\x13\x66ila/v1/admin.proto\x12\x07\x66ila.v1\"H\n\x12\x43reateQueueRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12$\n\x06\x63onfig\x18\x02 \x01(\x0b\x32\x14.fila.v1.QueueConfig\"b\n\x0bQueueConfig\x12\x19\n\x11on_enqueue_script\x18\x01 \x01(\t\x12\x19\n\x11on_failure_script\x18\x02 \x01(\t\x12\x1d\n\x15visibility_timeout_ms\x18\x03 \x01(\x04\"\'\n\x13\x43reateQueueResponse\x12\x10\n\x08queue_id\x18\x01 \x01(\t\"#\n\x12\x44\x65leteQueueRequest\x12\r\n\x05queue\x18\x01 \x01(\t\"\x15\n\x13\x44\x65leteQueueResponse\".\n\x10SetConfigRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\x13\n\x11SetConfigResponse\"\x1f\n\x10GetConfigRequest\x12\x0b\n\x03key\x18\x01 \x01(\t\"\"\n\x11GetConfigResponse\x12\r\n\x05value\x18\x01 \x01(\t\")\n\x0b\x43onfigEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"#\n\x11ListConfigRequest\x12\x0e\n\x06prefix\x18\x01 \x01(\t\"P\n\x12ListConfigResponse\x12%\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x14.fila.v1.ConfigEntry\x12\x13\n\x0btotal_count\x18\x02 \x01(\r\" \n\x0fGetStatsRequest\x12\r\n\x05queue\x18\x01 \x01(\t\"b\n\x13PerFairnessKeyStats\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x15\n\rpending_count\x18\x02 \x01(\x04\x12\x17\n\x0f\x63urrent_deficit\x18\x03 \x01(\x03\x12\x0e\n\x06weight\x18\x04 \x01(\r\"Z\n\x13PerThrottleKeyStats\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x0e\n\x06tokens\x18\x02 \x01(\x01\x12\x17\n\x0frate_per_second\x18\x03 \x01(\x01\x12\r\n\x05\x62urst\x18\x04 \x01(\x01\"\xec\x01\n\x10GetStatsResponse\x12\r\n\x05\x64\x65pth\x18\x01 \x01(\x04\x12\x11\n\tin_flight\x18\x02 \x01(\x04\x12\x1c\n\x14\x61\x63tive_fairness_keys\x18\x03 \x01(\x04\x12\x18\n\x10\x61\x63tive_consumers\x18\x04 \x01(\r\x12\x0f\n\x07quantum\x18\x05 \x01(\r\x12\x33\n\rper_key_stats\x18\x06 \x03(\x0b\x32\x1c.fila.v1.PerFairnessKeyStats\x12\x38\n\x12per_throttle_stats\x18\x07 \x03(\x0b\x32\x1c.fila.v1.PerThrottleKeyStats\"2\n\x0eRedriveRequest\x12\x11\n\tdlq_queue\x18\x01 \x01(\t\x12\r\n\x05\x63ount\x18\x02 \x01(\x04\"#\n\x0fRedriveResponse\x12\x10\n\x08redriven\x18\x01 \x01(\x04\"\x13\n\x11ListQueuesRequest\"U\n\tQueueInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x64\x65pth\x18\x02 \x01(\x04\x12\x11\n\tin_flight\x18\x03 \x01(\x04\x12\x18\n\x10\x61\x63tive_consumers\x18\x04 \x01(\r\"8\n\x12ListQueuesResponse\x12\"\n\x06queues\x18\x01 \x03(\x0b\x32\x12.fila.v1.QueueInfo2\xb4\x04\n\tFilaAdmin\x12H\n\x0b\x43reateQueue\x12\x1b.fila.v1.CreateQueueRequest\x1a\x1c.fila.v1.CreateQueueResponse\x12H\n\x0b\x44\x65leteQueue\x12\x1b.fila.v1.DeleteQueueRequest\x1a\x1c.fila.v1.DeleteQueueResponse\x12\x42\n\tSetConfig\x12\x19.fila.v1.SetConfigRequest\x1a\x1a.fila.v1.SetConfigResponse\x12\x42\n\tGetConfig\x12\x19.fila.v1.GetConfigRequest\x1a\x1a.fila.v1.GetConfigResponse\x12\x45\n\nListConfig\x12\x1a.fila.v1.ListConfigRequest\x1a\x1b.fila.v1.ListConfigResponse\x12?\n\x08GetStats\x12\x18.fila.v1.GetStatsRequest\x1a\x19.fila.v1.GetStatsResponse\x12<\n\x07Redrive\x12\x17.fila.v1.RedriveRequest\x1a\x18.fila.v1.RedriveResponse\x12\x45\n\nListQueues\x12\x1a.fila.v1.ListQueuesRequest\x1a\x1b.fila.v1.ListQueuesResponseb\x06proto3"
|
|
9
|
+
|
|
10
|
+
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
11
|
+
pool.add_serialized_file(descriptor_data)
|
|
12
|
+
|
|
13
|
+
module Fila
|
|
14
|
+
module V1
|
|
15
|
+
CreateQueueRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.CreateQueueRequest").msgclass
|
|
16
|
+
QueueConfig = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.QueueConfig").msgclass
|
|
17
|
+
CreateQueueResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.CreateQueueResponse").msgclass
|
|
18
|
+
DeleteQueueRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.DeleteQueueRequest").msgclass
|
|
19
|
+
DeleteQueueResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.DeleteQueueResponse").msgclass
|
|
20
|
+
SetConfigRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.SetConfigRequest").msgclass
|
|
21
|
+
SetConfigResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.SetConfigResponse").msgclass
|
|
22
|
+
GetConfigRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.GetConfigRequest").msgclass
|
|
23
|
+
GetConfigResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.GetConfigResponse").msgclass
|
|
24
|
+
ConfigEntry = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ConfigEntry").msgclass
|
|
25
|
+
ListConfigRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ListConfigRequest").msgclass
|
|
26
|
+
ListConfigResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ListConfigResponse").msgclass
|
|
27
|
+
GetStatsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.GetStatsRequest").msgclass
|
|
28
|
+
PerFairnessKeyStats = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.PerFairnessKeyStats").msgclass
|
|
29
|
+
PerThrottleKeyStats = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.PerThrottleKeyStats").msgclass
|
|
30
|
+
GetStatsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.GetStatsResponse").msgclass
|
|
31
|
+
RedriveRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.RedriveRequest").msgclass
|
|
32
|
+
RedriveResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.RedriveResponse").msgclass
|
|
33
|
+
ListQueuesRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ListQueuesRequest").msgclass
|
|
34
|
+
QueueInfo = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.QueueInfo").msgclass
|
|
35
|
+
ListQueuesResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ListQueuesResponse").msgclass
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
2
|
+
# Source: fila/v1/admin.proto for package 'fila.v1'
|
|
3
|
+
|
|
4
|
+
require 'grpc'
|
|
5
|
+
require 'fila/v1/admin_pb'
|
|
6
|
+
|
|
7
|
+
module Fila
|
|
8
|
+
module V1
|
|
9
|
+
module FilaAdmin
|
|
10
|
+
# Admin RPCs for operators and the CLI.
|
|
11
|
+
class Service
|
|
12
|
+
|
|
13
|
+
include ::GRPC::GenericService
|
|
14
|
+
|
|
15
|
+
self.marshal_class_method = :encode
|
|
16
|
+
self.unmarshal_class_method = :decode
|
|
17
|
+
self.service_name = 'fila.v1.FilaAdmin'
|
|
18
|
+
|
|
19
|
+
rpc :CreateQueue, ::Fila::V1::CreateQueueRequest, ::Fila::V1::CreateQueueResponse
|
|
20
|
+
rpc :DeleteQueue, ::Fila::V1::DeleteQueueRequest, ::Fila::V1::DeleteQueueResponse
|
|
21
|
+
rpc :SetConfig, ::Fila::V1::SetConfigRequest, ::Fila::V1::SetConfigResponse
|
|
22
|
+
rpc :GetConfig, ::Fila::V1::GetConfigRequest, ::Fila::V1::GetConfigResponse
|
|
23
|
+
rpc :ListConfig, ::Fila::V1::ListConfigRequest, ::Fila::V1::ListConfigResponse
|
|
24
|
+
rpc :GetStats, ::Fila::V1::GetStatsRequest, ::Fila::V1::GetStatsResponse
|
|
25
|
+
rpc :Redrive, ::Fila::V1::RedriveRequest, ::Fila::V1::RedriveResponse
|
|
26
|
+
rpc :ListQueues, ::Fila::V1::ListQueuesRequest, ::Fila::V1::ListQueuesResponse
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Stub = Service.rpc_stub_class
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: fila/v1/messages.proto
|
|
4
|
+
|
|
5
|
+
require 'google/protobuf'
|
|
6
|
+
|
|
7
|
+
require 'google/protobuf/timestamp_pb'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
descriptor_data = "\n\x16\x66ila/v1/messages.proto\x12\x07\x66ila.v1\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe2\x01\n\x07Message\x12\n\n\x02id\x18\x01 \x01(\t\x12.\n\x07headers\x18\x02 \x03(\x0b\x32\x1d.fila.v1.Message.HeadersEntry\x12\x0f\n\x07payload\x18\x03 \x01(\x0c\x12*\n\x08metadata\x18\x04 \x01(\x0b\x32\x18.fila.v1.MessageMetadata\x12.\n\ntimestamps\x18\x05 \x01(\x0b\x32\x1a.fila.v1.MessageTimestamps\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"w\n\x0fMessageMetadata\x12\x14\n\x0c\x66\x61irness_key\x18\x01 \x01(\t\x12\x0e\n\x06weight\x18\x02 \x01(\r\x12\x15\n\rthrottle_keys\x18\x03 \x03(\t\x12\x15\n\rattempt_count\x18\x04 \x01(\r\x12\x10\n\x08queue_id\x18\x05 \x01(\t\"s\n\x11MessageTimestamps\x12/\n\x0b\x65nqueued_at\x18\x01 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12-\n\tleased_at\x18\x02 \x01(\x0b\x32\x1a.google.protobuf.Timestampb\x06proto3"
|
|
11
|
+
|
|
12
|
+
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
13
|
+
pool.add_serialized_file(descriptor_data)
|
|
14
|
+
|
|
15
|
+
module Fila
|
|
16
|
+
module V1
|
|
17
|
+
Message = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.Message").msgclass
|
|
18
|
+
MessageMetadata = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.MessageMetadata").msgclass
|
|
19
|
+
MessageTimestamps = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.MessageTimestamps").msgclass
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: fila/v1/service.proto
|
|
4
|
+
|
|
5
|
+
require 'google/protobuf'
|
|
6
|
+
|
|
7
|
+
require 'fila/v1/messages_pb'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
descriptor_data = "\n\x15\x66ila/v1/service.proto\x12\x07\x66ila.v1\x1a\x16\x66ila/v1/messages.proto\"\x97\x01\n\x0e\x45nqueueRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x35\n\x07headers\x18\x02 \x03(\x0b\x32$.fila.v1.EnqueueRequest.HeadersEntry\x12\x0f\n\x07payload\x18\x03 \x01(\x0c\x1a.\n\x0cHeadersEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"%\n\x0f\x45nqueueResponse\x12\x12\n\nmessage_id\x18\x01 \x01(\t\"\x1f\n\x0e\x43onsumeRequest\x12\r\n\x05queue\x18\x01 \x01(\t\"4\n\x0f\x43onsumeResponse\x12!\n\x07message\x18\x01 \x01(\x0b\x32\x10.fila.v1.Message\"/\n\nAckRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x12\n\nmessage_id\x18\x02 \x01(\t\"\r\n\x0b\x41\x63kResponse\"?\n\x0bNackRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x12\n\nmessage_id\x18\x02 \x01(\t\x12\r\n\x05\x65rror\x18\x03 \x01(\t\"\x0e\n\x0cNackResponse2\xf2\x01\n\x0b\x46ilaService\x12<\n\x07\x45nqueue\x12\x17.fila.v1.EnqueueRequest\x1a\x18.fila.v1.EnqueueResponse\x12>\n\x07\x43onsume\x12\x17.fila.v1.ConsumeRequest\x1a\x18.fila.v1.ConsumeResponse0\x01\x12\x30\n\x03\x41\x63k\x12\x13.fila.v1.AckRequest\x1a\x14.fila.v1.AckResponse\x12\x33\n\x04Nack\x12\x14.fila.v1.NackRequest\x1a\x15.fila.v1.NackResponseb\x06proto3"
|
|
11
|
+
|
|
12
|
+
pool = ::Google::Protobuf::DescriptorPool.generated_pool
|
|
13
|
+
pool.add_serialized_file(descriptor_data)
|
|
14
|
+
|
|
15
|
+
module Fila
|
|
16
|
+
module V1
|
|
17
|
+
EnqueueRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.EnqueueRequest").msgclass
|
|
18
|
+
EnqueueResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.EnqueueResponse").msgclass
|
|
19
|
+
ConsumeRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ConsumeRequest").msgclass
|
|
20
|
+
ConsumeResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.ConsumeResponse").msgclass
|
|
21
|
+
AckRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.AckRequest").msgclass
|
|
22
|
+
AckResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.AckResponse").msgclass
|
|
23
|
+
NackRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.NackRequest").msgclass
|
|
24
|
+
NackResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("fila.v1.NackResponse").msgclass
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
2
|
+
# Source: fila/v1/service.proto for package 'fila.v1'
|
|
3
|
+
|
|
4
|
+
require 'grpc'
|
|
5
|
+
require 'fila/v1/service_pb'
|
|
6
|
+
|
|
7
|
+
module Fila
|
|
8
|
+
module V1
|
|
9
|
+
module FilaService
|
|
10
|
+
# Hot-path RPCs for producers and consumers.
|
|
11
|
+
class Service
|
|
12
|
+
|
|
13
|
+
include ::GRPC::GenericService
|
|
14
|
+
|
|
15
|
+
self.marshal_class_method = :encode
|
|
16
|
+
self.unmarshal_class_method = :decode
|
|
17
|
+
self.service_name = 'fila.v1.FilaService'
|
|
18
|
+
|
|
19
|
+
rpc :Enqueue, ::Fila::V1::EnqueueRequest, ::Fila::V1::EnqueueResponse
|
|
20
|
+
rpc :Consume, ::Fila::V1::ConsumeRequest, stream(::Fila::V1::ConsumeResponse)
|
|
21
|
+
rpc :Ack, ::Fila::V1::AckRequest, ::Fila::V1::AckResponse
|
|
22
|
+
rpc :Nack, ::Fila::V1::NackRequest, ::Fila::V1::NackResponse
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
Stub = Service.rpc_stub_class
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/fila/version.rb
ADDED
data/lib/fila.rb
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
package fila.v1;
|
|
3
|
+
|
|
4
|
+
// Admin RPCs for operators and the CLI.
|
|
5
|
+
service FilaAdmin {
|
|
6
|
+
rpc CreateQueue(CreateQueueRequest) returns (CreateQueueResponse);
|
|
7
|
+
rpc DeleteQueue(DeleteQueueRequest) returns (DeleteQueueResponse);
|
|
8
|
+
rpc SetConfig(SetConfigRequest) returns (SetConfigResponse);
|
|
9
|
+
rpc GetConfig(GetConfigRequest) returns (GetConfigResponse);
|
|
10
|
+
rpc ListConfig(ListConfigRequest) returns (ListConfigResponse);
|
|
11
|
+
rpc GetStats(GetStatsRequest) returns (GetStatsResponse);
|
|
12
|
+
rpc Redrive(RedriveRequest) returns (RedriveResponse);
|
|
13
|
+
rpc ListQueues(ListQueuesRequest) returns (ListQueuesResponse);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
message CreateQueueRequest {
|
|
17
|
+
string name = 1;
|
|
18
|
+
QueueConfig config = 2;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
message QueueConfig {
|
|
22
|
+
string on_enqueue_script = 1;
|
|
23
|
+
string on_failure_script = 2;
|
|
24
|
+
uint64 visibility_timeout_ms = 3;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
message CreateQueueResponse {
|
|
28
|
+
string queue_id = 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
message DeleteQueueRequest {
|
|
32
|
+
string queue = 1;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
message DeleteQueueResponse {}
|
|
36
|
+
|
|
37
|
+
message SetConfigRequest {
|
|
38
|
+
string key = 1;
|
|
39
|
+
string value = 2;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
message SetConfigResponse {}
|
|
43
|
+
|
|
44
|
+
message GetConfigRequest {
|
|
45
|
+
string key = 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
message GetConfigResponse {
|
|
49
|
+
string value = 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
message ConfigEntry {
|
|
53
|
+
string key = 1;
|
|
54
|
+
string value = 2;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
message ListConfigRequest {
|
|
58
|
+
string prefix = 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
message ListConfigResponse {
|
|
62
|
+
repeated ConfigEntry entries = 1;
|
|
63
|
+
uint32 total_count = 2;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
message GetStatsRequest {
|
|
67
|
+
string queue = 1;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
message PerFairnessKeyStats {
|
|
71
|
+
string key = 1;
|
|
72
|
+
uint64 pending_count = 2;
|
|
73
|
+
int64 current_deficit = 3;
|
|
74
|
+
uint32 weight = 4;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
message PerThrottleKeyStats {
|
|
78
|
+
string key = 1;
|
|
79
|
+
double tokens = 2;
|
|
80
|
+
double rate_per_second = 3;
|
|
81
|
+
double burst = 4;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
message GetStatsResponse {
|
|
85
|
+
uint64 depth = 1;
|
|
86
|
+
uint64 in_flight = 2;
|
|
87
|
+
uint64 active_fairness_keys = 3;
|
|
88
|
+
uint32 active_consumers = 4;
|
|
89
|
+
uint32 quantum = 5;
|
|
90
|
+
repeated PerFairnessKeyStats per_key_stats = 6;
|
|
91
|
+
repeated PerThrottleKeyStats per_throttle_stats = 7;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
message RedriveRequest {
|
|
95
|
+
string dlq_queue = 1;
|
|
96
|
+
uint64 count = 2;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
message RedriveResponse {
|
|
100
|
+
uint64 redriven = 1;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
message ListQueuesRequest {}
|
|
104
|
+
|
|
105
|
+
message QueueInfo {
|
|
106
|
+
string name = 1;
|
|
107
|
+
uint64 depth = 2;
|
|
108
|
+
uint64 in_flight = 3;
|
|
109
|
+
uint32 active_consumers = 4;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
message ListQueuesResponse {
|
|
113
|
+
repeated QueueInfo queues = 1;
|
|
114
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
package fila.v1;
|
|
3
|
+
|
|
4
|
+
import "google/protobuf/timestamp.proto";
|
|
5
|
+
|
|
6
|
+
// Core message envelope persisted in the broker.
|
|
7
|
+
message Message {
|
|
8
|
+
string id = 1;
|
|
9
|
+
map<string, string> headers = 2;
|
|
10
|
+
bytes payload = 3;
|
|
11
|
+
MessageMetadata metadata = 4;
|
|
12
|
+
MessageTimestamps timestamps = 5;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Broker-assigned scheduling metadata.
|
|
16
|
+
message MessageMetadata {
|
|
17
|
+
string fairness_key = 1;
|
|
18
|
+
uint32 weight = 2;
|
|
19
|
+
repeated string throttle_keys = 3;
|
|
20
|
+
uint32 attempt_count = 4;
|
|
21
|
+
string queue_id = 5;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Lifecycle timestamps attached to every message.
|
|
25
|
+
message MessageTimestamps {
|
|
26
|
+
google.protobuf.Timestamp enqueued_at = 1;
|
|
27
|
+
google.protobuf.Timestamp leased_at = 2;
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
package fila.v1;
|
|
3
|
+
|
|
4
|
+
import "fila/v1/messages.proto";
|
|
5
|
+
|
|
6
|
+
// Hot-path RPCs for producers and consumers.
|
|
7
|
+
service FilaService {
|
|
8
|
+
rpc Enqueue(EnqueueRequest) returns (EnqueueResponse);
|
|
9
|
+
rpc Consume(ConsumeRequest) returns (stream ConsumeResponse);
|
|
10
|
+
rpc Ack(AckRequest) returns (AckResponse);
|
|
11
|
+
rpc Nack(NackRequest) returns (NackResponse);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
message EnqueueRequest {
|
|
15
|
+
string queue = 1;
|
|
16
|
+
map<string, string> headers = 2;
|
|
17
|
+
bytes payload = 3;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
message EnqueueResponse {
|
|
21
|
+
string message_id = 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
message ConsumeRequest {
|
|
25
|
+
string queue = 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
message ConsumeResponse {
|
|
29
|
+
Message message = 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
message AckRequest {
|
|
33
|
+
string queue = 1;
|
|
34
|
+
string message_id = 2;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
message AckResponse {}
|
|
38
|
+
|
|
39
|
+
message NackRequest {
|
|
40
|
+
string queue = 1;
|
|
41
|
+
string message_id = 2;
|
|
42
|
+
string error = 3;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
message NackResponse {}
|