Conversation
108e261 to
8227b62
Compare
174b8fe to
04cc96d
Compare
| max = send("max_#{type}") | ||
|
|
||
| if threshold.nil? | ||
| instance_variable_set("@threshold_#{type}", max / 2) |
There was a problem hiding this comment.
it needs to be possible to also be able to make a batch request with both max msgs and max bytes limits, in the Go client it is an option called: PullMaxMessagesWithBytesLimit that always makes fetch requests using the same max_bytes https://github.com/nats-io/nats.go/pull/1789/files
There was a problem hiding this comment.
Updated the consume config, so now consume can accept both max_messages and max_bytes parameters.
df550c3 to
7195367
Compare
4a58ad4 to
595189b
Compare
wallyqs
left a comment
There was a problem hiding this comment.
Ran into a few import issues running the examples, this should be ok usage right?
require 'nats'
nc = NATS.connect
jsctx = NATS::JetStream::Context.new(nc)
| @@ -0,0 +1,45 @@ | |||
| # frozen_string_literal: true | |||
|
|
|||
| require "nats" | |||
There was a problem hiding this comment.
I tried running this example and got the following, maybe there is a missing require?
# bundle exec ruby examples/jetstream/consume.rb
nats-pure.rb/lib/nats/io/client.rb:869:in 'NATS::Client#js': uninitialized constant NATS::JetStream::Context (NameError)
::NATS::JetStream::Context.new(self, options)
^^^^^^^^^
from examples/jetstream/consume.rb:6:in '<main>'
There was a problem hiding this comment.
Fixed requires in nats.rb that caused the issue.
Please note that if you run examples with ruby path/to/example.rb you need to build and install the gem locally:
gem build
gem install nats-pure-2.5.0.gem
Or you can run bundle console and copy the code there.
|
|
||
| # Simplified JetStream API | ||
| def js(options = {}) | ||
| ::NATS::JetStream::Context.new(self, options) |
There was a problem hiding this comment.
Running into this when running an example, maybe there is a missing require?
bundle exec ruby examples/jetstream/next.rb
...nats-pure.rb/lib/nats/io/client.rb:869:in 'NATS::Client#js': uninitialized constant NATS::JetStream::Context (NameError)
::NATS::JetStream::Context.new(self, options)
| ```ruby | ||
| client = NATS.connect | ||
|
|
||
| js = NATS::JetStream::Context.new(client) |
There was a problem hiding this comment.
could you include the requires in the examples as well? I tried this but ran into loading issues
require 'nats'
nc = NATS.connect
jsctx = NATS::JetStream::Context.new(nc)lib/nats/jetstream/stream/schemas.rb:7:in '<class:Stream>': uninitialized constant NATS::Utils::Config (NameError)
class SubjectTransform < NATS::Utils::Config
| class JetStream | ||
| class Stream | ||
| # Subject transform to apply to matching messages going into the stream | ||
| class SubjectTransform < NATS::Utils::Config |
There was a problem hiding this comment.
could it be that this file missing some requires?
|
What's left in order to merge it? |
This is an implementation of JetStream Simplification.
Structure
The new API consists of several key objects:
API
The purpose of
Apiobject is to simplify working with JetStream API:nats-pure.rb/lib/nats/jetstream/api.rb
Lines 11 to 29 in f548e3f
API endpoints are defined with custom dsl methods
groupandendpoint. The dsl magic is implemented inDSL,GroupandEndpointclasses and uses Ruby meta programming.The
groupmethod helps to create an endpoints hierarchy. Theendpointmethod defines an endpoint using:requestthat defines what options can be sent to the endpoint,responsethat describes the structure of the endpoint response,subjectdefines whether or not the endpoint accepts a subject as its first field.Different types of requests and responses are described in
api/requestsandapi/responsedirectories.With the api object, making a request looks just like the request subject, which greatly simplifies the code that uses it. For example, to make an API request to
$JS.API.STREAM.MSG.GET.*you just writeContext
Since the Legacy JetStream API "occupies" the
JetStreamobject, I made a new class,Context, to be an entry point to the simplified API.It initializes an
Apiinstance underneath, provides methods for accessinginfoandstreams, and publishing messages withpublish.Stream
A single stream is represented by the
Streamclass. Most of the Stream subclasses define different internal parts of a stream, such as:Stream::Configdefines a stream config.Stream::Infodefines data that is returned byapi.stream.info.Stream::Statedefines a stream state object.stream/schemas.rbcontains definitions for Info sub-objects, such as SubjectTransfrom, ExternalStream, and StreamSource.Each stream has methods to manage it:
info,update,delete, andpurge.List
Stream::Listencapsulates the logic of finding, creating and iterating over streams/names. The iteration is implemented via a Ruby Enumerator object that makes subsequentapi.stream.list/namesrequests.Consumer
The
Consumerclass represents a consumer. It has a set of sub-classes similar to a stream:Consumer::Configdefines a consumer config.Consumer::Infodefines data that is returned byapi.consumer.info.consumer/schemas.rbcontains definitions for Info sub-objects, such as Limits and SequenceInfo.A consumer has
info,updateanddeletemethods that uses api requests underneath.List
Consumer::Listencapsulates the logic of finding, creating and iterating over consumers/names. The iteration is implemented in the same way as for streams: via a Ruby Enumerator object that makes subsequentapi.consumer.list/namesrequests.Fetch
The
Consumer::Fetchwraps up aFetchpull and adds iterator like behaviour to it. The fetch operation blocks until all the messages are received or the pull expires. For more onFetchsee the Pull section.Message
The
Messageclass is a base for JetStream messages that can be divided into 4 groups:stream.messages.findmethod, and it has only one methoddelete.ack,nack,termandin_progress.Message.buildmethod builds a JetStream message from a NATS message by checking its "Status" and "Description" headers.Pull
Pullis the basis for the fetch and consume operations. A pull consists ofEach pull has a status field: pending, processing, draining or closed.
The workflow of the pull has only 2 steps:
startthat starts the pull execution,drainthat starts draining the pull.You can wait until a pull is closed with
#waitmethod that blocks until the pull is closed or timeout seconds pass.Fetch
Fetch::Handlerhandles messages in the following way:ConsumerMessage- resets heartbeats, stores the message in the buffer, initiates drain if the buffer is full.IdleHeartbeatMessage- resets heartbeats.WarningMessage- stores the message description inlast_error, drains the pull.ErrorMessager- stores the message description inlast_error, drains the pull.Fetch::Bufferhas three methods:fetched(message)stores a message and tracks the number of messages/bytes fetched so far,full?returns true if the number of messages/bytes fetched,messages- an array of fetched messages.Fetch::Heartbeatssets aConcurrent::ScheduledTasktask for monitoring heartbeats. Every time a consumer or idle heartbeat message is received, the heartbeats task is rescheduled. If no messages are received or the pull request expires, the pull initiates drain.Fetch::Timeoutsets aConcurrent::ScheduledTasktask for monitoring timeouts that will be executed after a fetch requests expires.Consume
Consume::Handlerhandles messages in the following way:ConsumerMessage- resets heartbeats, calls the user defined block, tracks the message in the buffer, requests new messages if the buffer is depleting.IdleHeartbeatMessage- resets heartbeats.WarningMessage- resets heartbeats, update the buffer if the message contains "Nats-Pending" headers, requests new messages if the buffer is depleting.ErrorMessager- stores the message description inlast_error, drains the pull.Consume::Bufferhas four methods:consumed(message)tracks the number of messages/bytes pending,depleting?returns true if the number of messages/bytes pending falls below the threshold,refill- refills the number of messages/bytes pending indicating that a new batch of messages has been requested,trim(message)- decrease the number of messages/bytes pending by "Nats-Pending" headers.Consume::Heartbeatssets aConcurrent::ScheduledTasktask for monitoring heartbeats. The heartbeats task is rescheduled whenever a consumer or idle heartbeat message is received. If no messages are received, the pull requests new messages.Fetch::Connectionregisters a new status listener that listens to reconnecting/connected statuses (the idea is inspired by the Go client) and creates a separate thread that monitors the client connection via the status listener and stops/reschedules heartbeats depending on the client status.Publish
A
Publisherobject implements publishing messages. It definespublishmethod that:Publisher::Options,Publisher::Ackobject.nats-pure.rb/lib/nats/jetstream/publisher.rb
Lines 15 to 30 in f548e3f
Legacy vs Simplified API
The Legacy JetStream API is available as usual via
jetstreamandjsmmethodsThe Simplified JetStream API can be accessed through the new
jsmethod or by creating a JetStream context object: