omq-rs 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: deaed5d4439c9c15105ab96ca99b1589052d80bdf0730d07aff19f7b146cdc47
4
- data.tar.gz: 116dc7537c497dc57a59a5348966dc6c5f82bf3dea038ddc488eef7aa6efb470
3
+ metadata.gz: 529730a7fd3a4fe212f423bd4404fe12d5b33818cc2ec80df6e971183464f98f
4
+ data.tar.gz: 6af2f40b2a2a3dda39d761b6125df5c0d7eb252e0928725caed653d2bfa8f5e4
5
5
  SHA512:
6
- metadata.gz: c82ec7acb65d986cdc8f0d6289ac8fd952b256cbe8b02276d0b1a84e4ff06fbb9f00dafa2373091bdcd17daeaffc53c4fff6a69d713a68d4b9aa9446e0c5bbbe
7
- data.tar.gz: e8b55702563c7849a521545c387ef91fbf632b329efad536105af4306d67f6fae31d914f3755c7be71639cd864241843d358417570c0451f5003a441f4b35f56
6
+ metadata.gz: 3704feceb32e6e3765de1c5450f0151e96a578ecfc8f6b1ae14a4e024eab25e700f88ae4c39dca36e259471993658e8ba4505d607a51843e60e87dbe83215770
7
+ data.tar.gz: 1e936ad84a6292b4a4f3a66ab64cc926a71095d136425fe640c67bfe051a73456199ba6bf59d3fa909248fc1591e2fb7afb4a16726e30100b9283aec0caeec09
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.1.1] - 2026-08-23
6
+
7
+ - Document the full public API and publish the RubyDoc documentation link.
8
+ - Reject unknown socket options instead of silently ignoring misspellings.
9
+ - Make peer, subscriber, and monitor waits stop cleanly when a socket closes.
10
+ - Release the CURVE auth-worker mutex before joining its thread during close.
11
+ - Add mixed transport, protocol, lifecycle, and resource soak coverage.
12
+ - Require `omq-proto` 0.26.1 and `omq-tokio` 0.21.4.
13
+
14
+ ## [0.1.0] - 2026-08-20
15
+
5
16
  - Add standalone `omq-rs` Ruby binding with all 20 OMQ socket types.
6
17
  - Add PLAIN and CURVE sockets, Z85 key generation, CURVE client authentication,
7
18
  and pyzmq CURVE interoperability.
data/DEVELOPMENT.md ADDED
@@ -0,0 +1,170 @@
1
+ # omq-rs development
2
+
3
+ Run commands from the repository root unless a section changes directory.
4
+
5
+ ## Prerequisites
6
+
7
+ - Ruby 3.3 or newer with Bundler.
8
+ - Rust 1.93 or newer with Cargo, rustfmt, and Clippy.
9
+ - Python with pyzmq for the Python interoperability tests.
10
+ - CZMQ and libzmq development files for cztop interoperability and both
11
+ benchmark baselines.
12
+
13
+ Install the Ruby dependencies:
14
+
15
+ ```sh
16
+ cd bindings/ruby
17
+ bundle install
18
+ ```
19
+
20
+ ## Build and test
21
+
22
+ Run the normal binding test pass from the repository root:
23
+
24
+ ```sh
25
+ ./scripts/test-ruby.sh
26
+ ```
27
+
28
+ Select a Ruby executable explicitly with `OMQ_RUBY`:
29
+
30
+ ```sh
31
+ OMQ_RUBY=/path/to/ruby ./scripts/test-ruby.sh
32
+ ```
33
+
34
+ The equivalent commands from the binding directory are:
35
+
36
+ ```sh
37
+ cd bindings/ruby
38
+ bundle exec rake
39
+ ```
40
+
41
+ Compile once, then run one test file:
42
+
43
+ ```sh
44
+ bundle exec rake compile
45
+ bundle exec ruby -Ilib:test test/test_features.rb
46
+ ```
47
+
48
+ The suite covers socket patterns, options, transports, CURVE, PLAIN,
49
+ compression, monitors, Fiber schedulers, Ractors, lifecycle behavior, and
50
+ pyzmq interoperability. pyzmq tests skip when pyzmq is unavailable. cztop
51
+ tests skip when CZMQ or cztop is unavailable. Ractor tests require Ruby 4.
52
+
53
+ ## Soak tests
54
+
55
+ Run the mixed transport, security, compression, churn, and resource soak:
56
+
57
+ ```sh
58
+ bindings/ruby/scripts/soak.sh 1h
59
+ ```
60
+
61
+ The duration accepts `s`, `m`, `h`, or `d`. The test reports progress, RSS,
62
+ file descriptors, and Ruby thread counts. It fails on message corruption,
63
+ stalls, or sustained resource growth.
64
+
65
+ `scripts/test-all.sh` includes the Ruby pass in the full repository test run.
66
+
67
+ ## Static checks
68
+
69
+ Run the same native checks as CI:
70
+
71
+ ```sh
72
+ cargo fmt --manifest-path bindings/ruby/Cargo.toml --all --check
73
+ cargo clippy --manifest-path bindings/ruby/Cargo.toml \
74
+ --all-targets --all-features -- -D warnings
75
+ ```
76
+
77
+ Check Ruby syntax:
78
+
79
+ ```sh
80
+ find bindings/ruby/lib bindings/ruby/test bindings/ruby/scripts \
81
+ -name '*.rb' -print0 | xargs -0 -n1 ruby -cw
82
+ ruby -cw bindings/ruby/Rakefile
83
+ ruby -cw bindings/ruby/omq-rs.gemspec
84
+ ```
85
+
86
+ Check public YARD coverage from `bindings/ruby` after installing YARD:
87
+
88
+ ```sh
89
+ yard stats --no-save --no-cache --list-undoc --no-private \
90
+ 'lib/**/*.rb' 'lib/*.rb'
91
+ ```
92
+
93
+ ## Benchmarks
94
+
95
+ Run benchmarks on an otherwise idle machine. The harness starts separate Ruby
96
+ processes over TCP. PUSH/PULL throughput covers 16 B through 32 KiB. REQ/REP
97
+ mean latency covers 16 B through 4 KiB. The default run keeps the median of three
98
+ rounds for each implementation, pattern, and message size. Throughput uses a
99
+ 0.5 second warmup and 2.5 second measurement window. Latency uses a 0.5 second
100
+ warmup and 1.5 second measurement window.
101
+
102
+ From the binding directory:
103
+
104
+ ```sh
105
+ cd bindings/ruby
106
+ bundle exec rake compile
107
+ bundle exec ruby -Ilib scripts/update_perf.rb
108
+ ```
109
+
110
+ The default run benchmarks `omq-rs`. It includes cztop when CZMQ is available
111
+ and ffi-rzmq when libzmq is available. Missing baselines are skipped.
112
+
113
+ Useful controls:
114
+
115
+ ```sh
116
+ bundle exec ruby -Ilib scripts/update_perf.rb --quick
117
+ bundle exec ruby -Ilib scripts/update_perf.rb --impl omq-rs,cztop,ffi-rzmq
118
+ bundle exec ruby -Ilib scripts/update_perf.rb --patterns pushpull,reqrep
119
+ bundle exec ruby -Ilib scripts/update_perf.rb --sizes 16,128,1024,4096
120
+ bundle exec ruby -Ilib scripts/update_perf.rb --rounds 5
121
+ bundle exec ruby -Ilib scripts/update_perf.rb --duration 2.5 --warmup-duration 0.5
122
+ bundle exec ruby -Ilib scripts/update_perf.rb --latency-duration 1.5 --latency-warmup-duration 0.5
123
+ bundle exec ruby -Ilib scripts/update_perf.rb --no-record
124
+ ```
125
+
126
+ `--quick` runs one round at 128 B and 1 KiB without recording results or
127
+ rewriting the chart.
128
+
129
+ ## Chart generation
130
+
131
+ Benchmark rows append to:
132
+
133
+ ```text
134
+ ~/.cache/omq-rs/bindings.jsonl
135
+ ```
136
+
137
+ Regenerate the SVG from the latest cached row for each implementation,
138
+ pattern, and message size:
139
+
140
+ ```sh
141
+ cd bindings/ruby
142
+ bundle exec ruby -Ilib scripts/update_perf.rb --chart-only
143
+ ```
144
+
145
+ The output is `bindings/ruby/doc/charts/bindings.svg`. Its hardware subtitle
146
+ comes from the repository-root `.chart_hw` file:
147
+
148
+ ```text
149
+ prefix=Linux VM on a 2018 Mac Mini
150
+ postfix=6 cores, performance governor, turbo off
151
+ ```
152
+
153
+ `.chart_hw` is local-only and gitignored.
154
+
155
+ ## Packaging and release
156
+
157
+ Build the source gem from the binding directory:
158
+
159
+ ```sh
160
+ cd bindings/ruby
161
+ bundle exec rake build
162
+ ```
163
+
164
+ The gem is written to `bindings/ruby/pkg/`. Publication runs only through
165
+ `.github/workflows/release-rubygems.yml` using RubyGems trusted publishing.
166
+ The release tag must match the gem version:
167
+
168
+ ```text
169
+ ruby-v<VERSION>
170
+ ```
data/README.md CHANGED
@@ -7,6 +7,16 @@ synchronous; its waits cooperate with an installed `Fiber.scheduler`.
7
7
  MRI 3.3+, MRI 4.0+, and TruffleRuby are supported. TruffleRuby 34 does not
8
8
  provide Ruby's `Fiber.scheduler` API, so waits block the calling thread there.
9
9
 
10
+ ## Performance
11
+
12
+ ![Ruby binding benchmark](doc/charts/bindings.svg)
13
+
14
+ The binding benchmark uses separate Ruby processes over TCP and compares
15
+ `omq-rs` with [cztop](https://github.com/paddor/cztop), which calls CZMQ and
16
+ libzmq through FFI, and [ffi-rzmq](https://github.com/chuckremes/ffi-rzmq),
17
+ which calls libzmq directly through FFI. See [DEVELOPMENT.md](DEVELOPMENT.md)
18
+ for methodology and regeneration commands.
19
+
10
20
  ## Install
11
21
 
12
22
  ```sh
@@ -131,30 +141,7 @@ TCP endpoints; no preparation call is required.
131
141
 
132
142
  ## Development
133
143
 
134
- ```sh
135
- bundle install
136
- bundle exec rake
137
- ```
138
-
139
- ## Performance
140
-
141
- ![Ruby binding benchmark](doc/charts/bindings.svg)
142
-
143
- The binding benchmark uses separate Ruby processes over TCP and compares
144
- `omq-rs` with [cztop](https://github.com/paddor/cztop), which calls CZMQ and
145
- libzmq through FFI, and [ffi-rzmq](https://github.com/chuckremes/ffi-rzmq),
146
- which calls libzmq directly through FFI. Install CZMQ and libzmq to include
147
- both baselines.
148
-
149
- ```sh
150
- ruby -Ilib scripts/update_perf.rb
151
- ruby -Ilib scripts/update_perf.rb --quick
152
- ruby -Ilib scripts/update_perf.rb --chart-only
153
- ```
154
-
155
- Rows append to `~/.cache/omq-rs/bindings.jsonl`. The generated chart is
156
- `doc/charts/bindings.svg`. `--quick` only runs a smoke benchmark and does not
157
- write results or a chart.
144
+ Build, test, benchmark, and release instructions: [DEVELOPMENT.md](DEVELOPMENT.md).
158
145
 
159
146
  ## License
160
147
 
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "omq_rs_native"
3
- version = "0.1.0"
3
+ version = "0.1.1"
4
4
  edition = "2024"
5
5
  rust-version = "1.93"
6
6
  license = "ISC"
@@ -20,8 +20,8 @@ zstd = ["omq-tokio/zstd"]
20
20
  ws = ["omq-tokio/ws"]
21
21
 
22
22
  [dependencies]
23
- omq-proto = { version = ">=0.26.0, <0.28.0", default-features = false }
24
- omq-tokio = { version = ">=0.21.3, <0.23.0", default-features = false }
23
+ omq-proto = { version = ">=0.26.1, <0.28.0", default-features = false }
24
+ omq-tokio = { version = ">=0.21.4, <0.23.0", default-features = false }
25
25
  yring = { version = "=0.3.14", features = ["async"] }
26
26
 
27
27
  bytes = "1.12.0"
@@ -198,7 +198,8 @@ fn set_curve_authenticator(
198
198
  }
199
199
  drop(options_guard);
200
200
 
201
- if let Some(previous) = rb_self.auth_worker.lock().unwrap().take() {
201
+ let previous = rb_self.auth_worker.lock().unwrap().take();
202
+ if let Some(previous) = previous {
202
203
  previous.stop();
203
204
  }
204
205
  *rb_self.auth_worker.lock().unwrap() = worker;
@@ -774,7 +775,8 @@ unsafe extern "C" fn rust_socket_leave(rb_self: VALUE, group: VALUE) -> VALUE {
774
775
  fn rust_socket_close_impl(rb_self: &RustSocket, wait_for_auth_worker: bool) {
775
776
  rb_self.closed.store(true, Ordering::Relaxed);
776
777
  #[cfg(feature = "curve")]
777
- if let Some(worker) = rb_self.auth_worker.lock().unwrap().take() {
778
+ let worker = rb_self.auth_worker.lock().unwrap().take();
779
+ if let Some(worker) = worker {
778
780
  if wait_for_auth_worker {
779
781
  worker.stop();
780
782
  } else {
data/lib/omq/rs/socket.rb CHANGED
@@ -18,6 +18,69 @@ module OMQ
18
18
  # @api private
19
19
  SINGLE_FRAME_TYPES = %i[client server scatter gather channel].freeze
20
20
 
21
+ # @api private
22
+ SOCKET_OPTIONS = %w[
23
+ workload_profile
24
+ send_hwm
25
+ recv_hwm
26
+ recv_rate_limit
27
+ recv_ip_rate_limit
28
+
29
+ linger
30
+ identity
31
+ router_mandatory
32
+ conflate
33
+
34
+ heartbeat_interval
35
+ heartbeat_ttl
36
+ heartbeat_timeout
37
+ handshake_timeout
38
+ max_pending_handshakes
39
+
40
+ max_message_size
41
+ sndbuf
42
+ rcvbuf
43
+ large_message_threshold
44
+ arena_threshold
45
+ transmit_slot_cap
46
+
47
+ xpub_nodrop
48
+ reconnect_stop_conn_refused
49
+ on_mute
50
+ reconnect_interval
51
+ reconnect_interval_min
52
+ reconnect_interval_max
53
+
54
+ compression_dict
55
+ compression_auto_train
56
+ compression_threshold
57
+ compression_level
58
+ compression_dict_capacity
59
+ max_recv_dict_size
60
+ compression_offload_threshold
61
+
62
+ mechanism_type
63
+ mechanism_server
64
+ mechanism_public_key
65
+ mechanism_secret_key
66
+ mechanism_server_key
67
+ mechanism_username
68
+ mechanism_password
69
+
70
+ curve_server
71
+ curve_publickey
72
+ curve_public_key
73
+ curve_secretkey
74
+ curve_secret_key
75
+ curve_serverkey
76
+ curve_server_key
77
+
78
+ plain_server
79
+ plain_username
80
+ plain_password
81
+ ].freeze
82
+ private_constant :ROUTED_TYPES, :SINGLE_FRAME_TYPES, :SOCKET_OPTIONS
83
+
21
84
  # CURVE peer metadata passed to callable authenticators.
22
85
  #
23
86
  # @!attribute [r] public_key
@@ -34,11 +97,13 @@ module OMQ
34
97
  Native.io_threads
35
98
  end
36
99
 
37
- # Sets number of OMQ.rs IO threads used by subsequently created sockets.
100
+ # Sets number of OMQ.rs IO threads before the shared runtime starts.
38
101
  #
39
102
  # @param count [Integer] positive IO thread count
40
103
  # @return [Integer] assigned count
41
104
  # @raise [ArgumentError] if +count+ is not positive
105
+ # @note Set this before materializing any socket. It does not resize a
106
+ # running runtime.
42
107
  def io_threads=(count)
43
108
  count = Integer(count)
44
109
  raise ArgumentError, "io_threads must be positive" unless count.positive?
@@ -139,7 +204,9 @@ module OMQ
139
204
  def each
140
205
  return enum_for(__method__) unless block_given?
141
206
 
142
- loop { yield recv }
207
+ while (event = recv)
208
+ yield event
209
+ end
143
210
  rescue IOError
144
211
  raise unless @socket.closed?
145
212
  end
@@ -156,8 +223,53 @@ module OMQ
156
223
  # @param send_timeout [Numeric, nil] send timeout in seconds
157
224
  # @param curve_auth [Array<String>, #call, nil] CURVE allowlist or authenticator
158
225
  # @param options [Hash] native OMQ.rs socket options
226
+ # @option options [Symbol] :workload_profile +:throughput+ or +:latency+
227
+ # @option options [Integer] :send_hwm outbound message capacity
228
+ # @option options [Integer] :recv_hwm inbound message capacity
229
+ # @option options [Hash] :recv_rate_limit per-connection
230
+ # +:messages_per_second+ (or +:rate+) and +:burst+
231
+ # @option options [Hash] :recv_ip_rate_limit per-IP
232
+ # +:messages_per_second+ (or +:rate+) and +:burst+
233
+ # @option options [Numeric] :linger close linger in seconds; positive
234
+ # infinity waits forever
235
+ # @option options [String] :identity ZMTP socket identity
236
+ # @option options [Boolean] :router_mandatory reject unroutable sends
237
+ # @option options [Boolean] :conflate retain only latest received message
238
+ # @option options [Numeric] :heartbeat_interval heartbeat period in seconds
239
+ # @option options [Numeric] :heartbeat_ttl remote heartbeat TTL in seconds
240
+ # @option options [Numeric] :heartbeat_timeout peer timeout in seconds
241
+ # @option options [Numeric] :handshake_timeout handshake timeout in seconds
242
+ # @option options [Integer] :max_pending_handshakes inbound handshake limit
243
+ # @option options [Integer] :max_message_size maximum received message bytes
244
+ # @option options [Integer] :sndbuf kernel send buffer bytes
245
+ # @option options [Integer] :rcvbuf kernel receive buffer bytes
246
+ # @option options [Integer] :large_message_threshold receive buffer threshold
247
+ # @option options [Integer] :arena_threshold contiguous frame arena threshold
248
+ # @option options [Integer] :transmit_slot_cap per-peer transmit bytes
249
+ # @option options [Boolean] :xpub_nodrop block instead of dropping on mute
250
+ # @option options [Boolean] :reconnect_stop_conn_refused stop refused reconnects
251
+ # @option options [Symbol] :on_mute +:block+, +:drop_newest+, or +:drop_oldest+
252
+ # @option options [Numeric] :reconnect_interval fixed reconnect delay in seconds
253
+ # @option options [Numeric] :reconnect_interval_min minimum backoff in seconds
254
+ # @option options [Numeric] :reconnect_interval_max maximum backoff in seconds
255
+ # @option options [String] :compression_dict compression dictionary bytes
256
+ # @option options [Boolean] :compression_auto_train train a zstd dictionary
257
+ # @option options [Integer] :compression_threshold minimum bytes to compress
258
+ # @option options [Integer] :compression_level zstd compression level
259
+ # @option options [Integer] :compression_dict_capacity trained dictionary bytes
260
+ # @option options [Integer] :max_recv_dict_size received dictionary byte limit
261
+ # @option options [Integer] :compression_offload_threshold offload threshold;
262
+ # negative disables offloading
263
+ # @option options [Symbol] :mechanism_type +:null+, +:plain+, or +:curve+
264
+ # @option options [Boolean] :plain_server enable PLAIN server mode
265
+ # @option options [String] :plain_username PLAIN client username
266
+ # @option options [String] :plain_password PLAIN client password
267
+ # @option options [Boolean] :curve_server enable CURVE server mode
268
+ # @option options [String] :curve_publickey local raw or Z85 public key
269
+ # @option options [String] :curve_secretkey local raw or Z85 secret key
270
+ # @option options [String] :curve_serverkey CURVE server raw or Z85 public key
159
271
  # @return [Socket]
160
- # @raise [ArgumentError] if an option is invalid
272
+ # @raise [ArgumentError] if an option is unknown or invalid
161
273
  def initialize(recv_timeout: nil, send_timeout: nil, curve_auth: nil, **options)
162
274
  socket_type = self.class.const_get(:SOCKET_TYPE, false)
163
275
  @socket_type = socket_type.to_s.downcase.to_sym
@@ -176,6 +288,8 @@ module OMQ
176
288
  @materialized = false
177
289
  @recv_io = nil
178
290
  @send_io = nil
291
+ @peer_connected = false
292
+ @subscriber_joined = false
179
293
  set_curve_auth(curve_auth) unless curve_auth.nil?
180
294
  end
181
295
 
@@ -228,7 +342,7 @@ module OMQ
228
342
  @native.peer_info(routing_id)
229
343
  end
230
344
 
231
- # Configures CURVE client authentication before socket materialization.
345
+ # Configures CURVE client authorization on a server before materialization.
232
346
  #
233
347
  # @param authenticator [Array<String>, #call, nil] public-key allowlist,
234
348
  # callable receiving {MechanismPeerInfo}, or +nil+ to allow valid clients
@@ -430,9 +544,16 @@ module OMQ
430
544
  # @param timeout [Numeric, nil] maximum wait in seconds
431
545
  # @return [Socket] self
432
546
  # @raise [IO::TimeoutError] if timeout expires
547
+ # @raise [IOError] if socket closes first
433
548
  def wait_for_peer(timeout: nil)
549
+ raise IOError, "socket closed" if closed?
550
+ return self if @peer_connected
551
+
434
552
  ensure_materialized
435
553
  wait_for_native_fd(@native.peer_connected_fd, timeout, "peer connection timed out")
554
+ raise IOError, "socket closed" if closed?
555
+
556
+ @peer_connected = true
436
557
  self
437
558
  end
438
559
 
@@ -441,9 +562,16 @@ module OMQ
441
562
  # @param timeout [Numeric, nil] maximum wait in seconds
442
563
  # @return [Socket] self
443
564
  # @raise [IO::TimeoutError] if timeout expires
565
+ # @raise [IOError] if socket closes first
444
566
  def wait_for_subscriber(timeout: nil)
567
+ raise IOError, "socket closed" if closed?
568
+ return self if @subscriber_joined
569
+
445
570
  ensure_materialized
446
571
  wait_for_native_fd(@native.subscriber_joined_fd, timeout, "subscriber timed out")
572
+ raise IOError, "socket closed" if closed?
573
+
574
+ @subscriber_joined = true
447
575
  self
448
576
  end
449
577
 
@@ -471,6 +599,8 @@ module OMQ
471
599
  # @return [Hash, nil]
472
600
  # @raise [IO::TimeoutError] if timeout expires
473
601
  def monitor_event(timeout: @recv_timeout)
602
+ return if closed?
603
+
474
604
  ensure_materialized
475
605
  event = @native.try_recv_monitor
476
606
  return event if event
@@ -483,6 +613,8 @@ module OMQ
483
613
  #
484
614
  # @return [Hash, nil]
485
615
  def try_monitor_event
616
+ return if closed?
617
+
486
618
  ensure_materialized
487
619
  @native.try_recv_monitor
488
620
  end
@@ -532,11 +664,17 @@ module OMQ
532
664
  end
533
665
 
534
666
  def normalize_options(options)
535
- options.to_h do |key, value|
667
+ normalized = options.to_h do |key, value|
536
668
  value = value.to_s if value.is_a?(Symbol)
537
669
  value = value.transform_keys(&:to_s) if value.is_a?(Hash)
538
670
  [key.to_s, value]
539
671
  end
672
+ unknown = normalized.keys - SOCKET_OPTIONS
673
+ unless unknown.empty?
674
+ raise ArgumentError, "unknown socket option#{"s" if unknown.length > 1}: #{unknown.sort.join(", ")}"
675
+ end
676
+
677
+ normalized
540
678
  end
541
679
 
542
680
  def validate_send_parts!(parts)
@@ -5,6 +5,6 @@ module OMQ
5
5
  module Rust
6
6
  # Ruby binding version.
7
7
  # @return [String]
8
- VERSION = "0.1.0"
8
+ VERSION = "0.1.1"
9
9
  end
10
10
  end
data/lib/omq/rs.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "rs/version"
4
4
  require_relative "rs/omq_rs_native"
5
5
  require_relative "rs/socket"
6
6
 
7
+ # Brokerless messaging APIs and language backends.
7
8
  module OMQ
8
9
  class << self
9
10
  # Returns the OMQ.rs namespace or creates an OMQ.rs-backed socket.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omq-rs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrik Wenger
@@ -33,6 +33,7 @@ extensions:
33
33
  extra_rdoc_files: []
34
34
  files:
35
35
  - CHANGELOG.md
36
+ - DEVELOPMENT.md
36
37
  - LICENSE
37
38
  - README.md
38
39
  - ext/omq_rs_native/Cargo.toml
@@ -56,6 +57,7 @@ licenses:
56
57
  metadata:
57
58
  source_code_uri: https://github.com/paddor/omq.rs/tree/main/bindings/ruby
58
59
  changelog_uri: https://github.com/paddor/omq.rs/tree/main/bindings/ruby/CHANGELOG.md
60
+ documentation_uri: https://www.rubydoc.info/gems/omq-rs
59
61
  rubygems_mfa_required: 'true'
60
62
  rdoc_options: []
61
63
  require_paths: