schwab_rb 1.0.5 → 1.0.6
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 +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +6 -0
- data/lib/schwab_rb/stream/async_client.rb +6 -0
- data/lib/schwab_rb/stream/base.rb +9 -17
- data/lib/schwab_rb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 931dc11bd7c59a66e180069c36ab7f6dd44cc068db8aa3c5b58ece0aaf830a6e
|
|
4
|
+
data.tar.gz: e9abc3aa0cce142ffe3ac9af5cca9ee9fa1e5d1fac7209e9f39c929c1f6f8f1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53af08e726ae79f7b672df90cab4486b88b1ffaedc19ebc7b666bde8362f4fe49667f78f8ffd390be215b0c975895f21b7b4a7ae34addbb41d94bbe4c3030807
|
|
7
|
+
data.tar.gz: 1ce70df60193ac32c02b50eb978c96a640ff75bf2715504824341daf4e51ec8a6c2e466a2598509a66195cfbba21a7724bba6f6b6a901946c5b5352df595f934
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.0.6] - 2026-11-13
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Stream services now retain one callback; registering another block for the same service replaces the previous callback.
|
|
7
|
+
- `Stream::AsyncClient` supports dynamic `add` and `unsub` operations.
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- Prevent duplicate callback invocation on repeated subscription additions and preserve callbacks when symbols are unsubscribed.
|
|
11
|
+
- Allow callback registration before symbols are supplied without sending an empty subscription.
|
|
12
|
+
|
|
3
13
|
## [1.0.5] - 2026-10-19
|
|
4
14
|
|
|
5
15
|
### Added
|
data/README.md
CHANGED
|
@@ -205,6 +205,12 @@ stream.unsub(:level_one_equities, symbols: ["SPY", "QQQ"])
|
|
|
205
205
|
stream.stop
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
+
Each service has one callback. Passing a block to `on` or `add` replaces its
|
|
209
|
+
callback; calls without a block preserve it, including after all symbols are
|
|
210
|
+
unsubscribed. You can register a callback with `on` before supplying symbols;
|
|
211
|
+
fields specified there are used when symbols are later added without fields.
|
|
212
|
+
Both `Stream::Client` and `Stream::AsyncClient` support `on`, `add`, and `unsub`.
|
|
213
|
+
|
|
208
214
|
## Data Objects
|
|
209
215
|
|
|
210
216
|
The gem includes structured data objects for better handling of API responses. Most API methods support a `return_data_objects` parameter (defaults to `true`) which returns parsed Ruby objects instead of raw JSON responses:
|
|
@@ -13,6 +13,12 @@ module SchwabRb
|
|
|
13
13
|
@stream.on(service_symbol, symbols: symbols, fields: fields, &block)
|
|
14
14
|
self
|
|
15
15
|
end
|
|
16
|
+
alias add on
|
|
17
|
+
|
|
18
|
+
def unsub(service_symbol, symbols: nil)
|
|
19
|
+
@stream.unsub(service_symbol, symbols: symbols)
|
|
20
|
+
self
|
|
21
|
+
end
|
|
16
22
|
|
|
17
23
|
def start
|
|
18
24
|
@stream.start
|
|
@@ -19,6 +19,7 @@ module SchwabRb
|
|
|
19
19
|
def initialize(client)
|
|
20
20
|
@client = client
|
|
21
21
|
@handlers = {}
|
|
22
|
+
@service_fields = {}
|
|
22
23
|
@subscriptions = {}
|
|
23
24
|
@connection = nil
|
|
24
25
|
@message_builder = nil
|
|
@@ -34,16 +35,18 @@ module SchwabRb
|
|
|
34
35
|
service_name = Services.lookup(service_symbol)
|
|
35
36
|
resolved_fields = fields ? Fields.resolve(service_name, fields) : nil
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
@
|
|
39
|
-
|
|
38
|
+
@handlers[service_name] = block if block
|
|
39
|
+
@service_fields[service_name] = resolved_fields unless fields.nil?
|
|
40
|
+
symbol_list = Array(symbols).map(&:to_s)
|
|
41
|
+
return self if symbol_list.empty?
|
|
40
42
|
|
|
43
|
+
subscription = { symbols: symbol_list, fields: resolved_fields || @service_fields[service_name] }
|
|
41
44
|
@subscriptions[service_name] = merge_subscription(
|
|
42
45
|
@subscriptions[service_name],
|
|
43
|
-
|
|
46
|
+
subscription
|
|
44
47
|
)
|
|
45
48
|
|
|
46
|
-
send_subscription(service_name,
|
|
49
|
+
send_subscription(service_name, subscription) if @connected
|
|
47
50
|
|
|
48
51
|
self
|
|
49
52
|
end
|
|
@@ -59,14 +62,6 @@ module SchwabRb
|
|
|
59
62
|
@subscriptions.delete(service_name) if @subscriptions[service_name][:symbols].empty?
|
|
60
63
|
end
|
|
61
64
|
|
|
62
|
-
if @handlers[service_name]
|
|
63
|
-
@handlers[service_name].each do |h|
|
|
64
|
-
h[:symbols] -= symbols_to_remove
|
|
65
|
-
end
|
|
66
|
-
@handlers[service_name].reject! { |h| h[:symbols].empty? }
|
|
67
|
-
@handlers.delete(service_name) if @handlers[service_name].empty?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
65
|
if @connected
|
|
71
66
|
request = @message_builder.build_request(
|
|
72
67
|
service_name, Commands::UNSUBS,
|
|
@@ -206,10 +201,7 @@ module SchwabRb
|
|
|
206
201
|
if parsed.key?("data")
|
|
207
202
|
parsed["data"].each do |data_entry|
|
|
208
203
|
service = data_entry["service"]
|
|
209
|
-
|
|
210
|
-
next unless handlers
|
|
211
|
-
|
|
212
|
-
handlers.each { |h| h[:callback]&.call(data_entry) }
|
|
204
|
+
@handlers[service]&.call(data_entry)
|
|
213
205
|
end
|
|
214
206
|
end
|
|
215
207
|
|
data/lib/schwab_rb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: schwab_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joseph Platta
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-11-14 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: async
|