nats-async 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5711fb8f1a7bcbb63a2e0f25f2d8c397840517af36b050486c51f97a5766d959
4
- data.tar.gz: cbe97a371adfb30e0f856941b791c61bbd79bb216e90d41b943e1d2fd962546f
3
+ metadata.gz: 14ba43d9d274e8b3bf2ed955560a480dcc9bf5c6668949b1007db1ebf17f02e8
4
+ data.tar.gz: fb0aa3853cbe25ddc1c61882b3e74031de3e916c6366d4450a7c750d4b27bdb7
5
5
  SHA512:
6
- metadata.gz: b28f9fe2b99bcc2acf765df56e0681c0ea616708b1bdd873a612495604eb7a445111a07d7e31058aac6dbaa10c7b8d3d6e16e3071bf2d11a032c102b83a84bdd
7
- data.tar.gz: dc559c667dfc89842ae802fd7d63263d6af0b63896f702a3f657636f1735093f9d4e77aa1ca9a56d9311695a3e8733063558f14f44ce3019b5245492619143ae
6
+ metadata.gz: 3d95c6affdcd42236c16e1f1264dfb1ef4c9cde64bf90fdfe775fceac5f90924bc3e9126b8590d8683fb369121a294a71e9cf8c901b27520c25e0ea814520ee9
7
+ data.tar.gz: cf6213706289cb5b3b6e97d6b2a1ac94c8d75053d50cf7dc9c746f22bc6ff465cc21207e086f2c17498c00ca83d152d761f9fa01e2ad7a23cdeb6c40fbff0e0a
data/.rspec CHANGED
@@ -1,3 +1,3 @@
1
1
  --color
2
2
  --require spec_helper
3
- --warnings
3
+ --warnings
data/README.md CHANGED
@@ -1,14 +1,6 @@
1
1
  # Nats Async
2
2
 
3
- `nats-async` packages the `nats-test` prototype as a Ruby gem with the same project layout and build flow as `dry-stack`.
4
-
5
- ```
6
- $ ./bin/nats-async --help
7
- Usage: nats-async [--version] [--help]
8
-
9
- Library gem for the NatsAsync connector prototype.
10
-
11
- ```
3
+ `nats-async` packages the `nats-test` is a Ruby gem.
12
4
 
13
5
  ## Installation
14
6
 
@@ -40,6 +32,22 @@ connector.run(duration: 1) do |client, task|
40
32
  end
41
33
  ```
42
34
 
35
+ ## Examples
36
+
37
+ Core pub/sub:
38
+
39
+ ```bash
40
+ bundle exec ruby examples/basic_pub_sub.rb
41
+ ```
42
+
43
+ JetStream publish and pull:
44
+
45
+ ```bash
46
+ bundle exec ruby examples/jetstream_roundtrip.rb
47
+ ```
48
+
49
+ The integration spec boots the bundled [`bin/nats-server`](bin/nats-server) and runs these examples locally.
50
+
43
51
  ## Development
44
52
 
45
53
  ```bash
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "nats-async"
6
+
7
+ url = ENV.fetch("NATS_URL", "nats://127.0.0.1:4222")
8
+ subject = ENV.fetch("NATS_SUBJECT", "demo.subject")
9
+ payload = ENV.fetch("NATS_PAYLOAD", "hello from nats-async")
10
+
11
+ connector = NatsAsync::SimpleConnector.new(url: url, verbose: true)
12
+
13
+ connector.run(duration: 1.5, ping_every: 1, ping_timeout: 1) do |client, task|
14
+ sid = client.subscribe(subject) do |message|
15
+ puts "received subject=#{message.subject} data=#{message.data.inspect}"
16
+ client.unsubscribe(sid)
17
+ task.stop
18
+ end
19
+
20
+ client.publish(subject, payload)
21
+ end
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "nats-async"
6
+
7
+ url = ENV.fetch("NATS_URL", "nats://127.0.0.1:4222")
8
+ stream_name = ENV.fetch("JS_STREAM", "test_stream")
9
+ subject = ENV.fetch("JS_SUBJECT", "test_stream")
10
+ consumer = ENV.fetch("JS_CONSUMER", "example_consumer")
11
+ payload = ENV.fetch("JS_PAYLOAD", "hello jetstream")
12
+ js_api_prefix = ENV.fetch("JS_API_PREFIX", "$JS.API")
13
+
14
+ connector = NatsAsync::SimpleConnector.new(
15
+ url: url,
16
+ verbose: true,
17
+ js_api_prefix: js_api_prefix
18
+ )
19
+
20
+ connector.run(duration: 3, ping_every: 1, ping_timeout: 1) do |client, _task|
21
+ client.request(
22
+ client.js_api_subject("STREAM.CREATE", stream_name),
23
+ {
24
+ name: stream_name,
25
+ subjects: [subject]
26
+ },
27
+ timeout: 2
28
+ )
29
+
30
+ client.request(
31
+ client.js_api_subject("CONSUMER.CREATE", stream_name, consumer),
32
+ {
33
+ stream_name: stream_name,
34
+ config: {
35
+ name: consumer,
36
+ durable_name: consumer,
37
+ ack_policy: "explicit",
38
+ deliver_policy: "new",
39
+ filter_subject: subject
40
+ }
41
+ },
42
+ timeout: 2
43
+ )
44
+
45
+ pub_ack = client.request(subject, payload, timeout: 2)
46
+ puts "published seq=#{pub_ack[:seq]} stream=#{pub_ack[:stream]}"
47
+
48
+ message = client.request(
49
+ client.js_api_subject("CONSUMER.MSG.NEXT", stream_name, consumer),
50
+ {batch: 1, expires: 1_000_000_000},
51
+ timeout: 2,
52
+ parse_json: false
53
+ )
54
+
55
+ puts "received subject=#{message.subject} data=#{message.data.inspect}"
56
+ puts "metadata=#{message.metadata.inspect}"
57
+ message.ack if message.reply
58
+
59
+ client.request(client.js_api_subject("CONSUMER.DELETE", stream_name, consumer), {}, timeout: 2)
60
+ client.request(client.js_api_subject("STREAM.DELETE", stream_name), {}, timeout: 2)
61
+ end
data/lib/nats-async.rb CHANGED
@@ -2,4 +2,3 @@
2
2
 
3
3
  require_relative "version"
4
4
  require_relative "nats_async/simple_connector"
5
- require_relative "nats_async/command_line"
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NatsAsync
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.3"
5
5
  end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable RSpec/ExampleLength, RSpec/NoExpectationExample
4
+ # rubocop:disable RSpec/DescribeClass
5
+
6
+ require_relative "spec_helper"
7
+
8
+ require "open3"
9
+ require "socket"
10
+ require "tempfile"
11
+ require "tmpdir"
12
+
13
+ RSpec.describe "example scripts" do
14
+ def report_server_start_failure(reason, log_path)
15
+ log = File.exist?(log_path) ? File.read(log_path) : "(log file missing)"
16
+ message = <<~MSG
17
+ nats-server example integration skipped: #{reason}
18
+ --- nats-server log ---
19
+ #{log}
20
+ --- end nats-server log ---
21
+ MSG
22
+
23
+ warn(message)
24
+ warn("::warning::#{message.gsub("\n", "%0A")}") if ENV["GITHUB_ACTIONS"] == "true"
25
+ skip(message)
26
+ end
27
+
28
+ def project_path = File.expand_path("..", __dir__)
29
+ def server_path = File.join(project_path, "bin", "nats-server")
30
+
31
+ def free_port
32
+ server = TCPServer.new("127.0.0.1", 0)
33
+ server.addr[1]
34
+ ensure
35
+ server&.close
36
+ end
37
+
38
+ def wait_for_server(port, server_pid, log_path, timeout: 5)
39
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
40
+
41
+ loop do
42
+ socket = TCPSocket.new("127.0.0.1", port)
43
+ socket.close
44
+ return
45
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
46
+ if Process.waitpid(server_pid, Process::WNOHANG)
47
+ report_server_start_failure("bundled nats-server exited before becoming ready", log_path)
48
+ end
49
+
50
+ if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
51
+ report_server_start_failure("bundled nats-server did not start on port #{port}", log_path)
52
+ end
53
+
54
+ sleep 0.1
55
+ end
56
+ end
57
+
58
+ def run_example(example_path, env)
59
+ stdout, stderr, status = Open3.capture3(env, "bundle", "exec", "ruby", example_path, chdir: project_path)
60
+ return if status.success?
61
+
62
+ raise <<~MSG
63
+ example failed: #{example_path}
64
+ status: #{status.exitstatus}
65
+ stdout:
66
+ #{stdout}
67
+ stderr:
68
+ #{stderr}
69
+ MSG
70
+ end
71
+
72
+ it "runs the bundled examples against the local nats-server" do
73
+ port = free_port
74
+ url = "nats://127.0.0.1:#{port}"
75
+ Tempfile.create(["nats-async-example", ".log"]) do |log|
76
+ log_path = log.path
77
+ Tempfile.create(["nats-async", ".conf"]) do |config|
78
+ config.write("debug: true\ntrace: true\n")
79
+ config.flush
80
+
81
+ Dir.mktmpdir("nats-async-js") do |store_dir|
82
+ server = Process.spawn(
83
+ server_path,
84
+ "-c", config.path,
85
+ "-js",
86
+ "-sd", store_dir,
87
+ "-p", port.to_s,
88
+ out: log,
89
+ err: log,
90
+ chdir: project_path
91
+ )
92
+
93
+ begin
94
+ wait_for_server(port, server, log_path)
95
+ run_example("examples/basic_pub_sub.rb", {"NATS_URL" => url})
96
+ run_example(
97
+ "examples/jetstream_roundtrip.rb",
98
+ {
99
+ "NATS_URL" => url,
100
+ "JS_STREAM" => "spec_stream",
101
+ "JS_SUBJECT" => "spec.subject",
102
+ "JS_CONSUMER" => "spec_consumer",
103
+ "JS_PAYLOAD" => "spec payload"
104
+ }
105
+ )
106
+ ensure
107
+ begin
108
+ Process.kill("TERM", server)
109
+ Process.wait(server)
110
+ rescue Errno::ESRCH, Process::Waiter::Error
111
+ nil
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ # rubocop:enable RSpec/ExampleLength, RSpec/NoExpectationExample
121
+ # rubocop:enable RSpec/DescribeClass
@@ -1,19 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- RSpec.describe NatsAsync do
4
- it "exposes a version" do
5
- expect(NatsAsync::VERSION).to eq("0.1.0")
6
- end
3
+ require_relative "spec_helper"
4
+
5
+ describe NatsAsync do
6
+ # it "exposes a version" do
7
+ # expect(NatsAsync::VERSION).to eq("0.1.0")
8
+ # end
7
9
 
8
10
  it "loads the simple connector" do
9
11
  expect(NatsAsync::SimpleConnector).to be_a(Class)
10
12
  end
11
-
12
- it "formats cli help" do
13
- output = StringIO.new
14
-
15
- NatsAsync::CommandLine.run([], stdout: output)
16
-
17
- expect(output.string).to include("Usage: nats-async")
18
- end
19
13
  end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nats-async
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
- - OpenAI Codex
7
+ - Artem Borodkin
8
8
  bindir: bin
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
@@ -183,33 +183,31 @@ dependencies:
183
183
  - - "~>"
184
184
  - !ruby/object:Gem::Version
185
185
  version: 0.5.1
186
- description: Lightweight async Ruby connector for NATS with request/reply and basic
187
- JetStream ack helpers.
186
+ description: Lightweight async Ruby connector for NATS
188
187
  email:
189
188
  - author@email.address
190
- executables:
191
- - nats-async
189
+ executables: []
192
190
  extensions: []
193
191
  extra_rdoc_files: []
194
192
  files:
195
193
  - ".github/workflows/release.yml"
196
194
  - ".rspec"
197
195
  - ".rubocop.yml"
198
- - README.erb
199
196
  - README.md
200
197
  - Rakefile
201
- - bin/nats-async
198
+ - examples/basic_pub_sub.rb
199
+ - examples/jetstream_roundtrip.rb
202
200
  - lib/nats-async.rb
203
- - lib/nats_async/command_line.rb
204
201
  - lib/nats_async/simple_connector.rb
205
202
  - lib/version.rb
203
+ - spec/examples_spec.rb
206
204
  - spec/nats_async_spec.rb
207
205
  - spec/spec_helper.rb
208
206
  homepage: https://rubygems.org/gems/nats-async
209
207
  licenses:
210
208
  - Nonstandard
211
209
  metadata:
212
- source_code_uri: https://github.com/example/nats-async
210
+ source_code_uri: https://github.com/artyomb/nats-async
213
211
  rdoc_options: []
214
212
  require_paths:
215
213
  - lib
@@ -226,5 +224,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
226
224
  requirements: []
227
225
  rubygems_version: 3.6.7
228
226
  specification_version: 4
229
- summary: Async NATS connector prototype packaged as a gem
227
+ summary: Async NATS connector
230
228
  test_files: []
data/README.erb DELETED
@@ -1,46 +0,0 @@
1
- # Nats Async
2
-
3
- `nats-async` packages the `nats-test` prototype as a Ruby gem with the same project layout and build flow as `dry-stack`.
4
-
5
- ```
6
- $ ./bin/nats-async --help
7
- <%= %x{./bin/nats-async --help} %>
8
- ```
9
-
10
- ## Installation
11
-
12
- Add the gem to your bundle:
13
-
14
- ```ruby
15
- gem "nats-async"
16
- ```
17
-
18
- Or install it directly:
19
-
20
- ```bash
21
- gem install nats-async
22
- ```
23
-
24
- ## Usage
25
-
26
- ```ruby
27
- require "nats-async"
28
-
29
- connector = NatsAsync::SimpleConnector.new(url: "nats://127.0.0.1:4222", verbose: false)
30
- connector.run(duration: 1) do |client, task|
31
- client.subscribe("demo.subject") do |message|
32
- puts "received: #{message.data}"
33
- task.stop
34
- end
35
-
36
- client.publish("demo.subject", "hello")
37
- end
38
- ```
39
-
40
- ## Development
41
-
42
- ```bash
43
- bundle install
44
- bundle exec rspec
45
- rake build
46
- ```
data/bin/nats-async DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path("../lib", __dir__)
4
- $LOAD_PATH << lib
5
-
6
- require "nats-async"
7
- require "nats_async/command_line"
8
-
9
- NatsAsync::CommandLine.run(ARGV)
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module NatsAsync
4
- module CommandLine
5
- module_function
6
-
7
- def run(argv, stdout: $stdout)
8
- case argv.first
9
- when "-v", "--version"
10
- stdout.puts(NatsAsync::VERSION)
11
- else
12
- stdout.puts("Usage: nats-async [--version] [--help]")
13
- stdout.puts
14
- stdout.puts("Library gem for the NatsAsync connector prototype.")
15
- end
16
- end
17
- end
18
- end