emb 0.2.4 → 0.2.5
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/README.md +62 -3
- data/lib/emb/client.rb +7 -2
- data/lib/emb/commands.rb +45 -0
- data/lib/emb/runtime_config.rb +47 -0
- data/lib/emb.rb +4 -2
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7fa662777093c5abee44186eba00b90fde9f1d3cd7bafcde73fc88748dd45478
|
|
4
|
+
data.tar.gz: ba3544c2dc3e1fc875f8d86d3448b8469fd194f2f9f9a12cbf2c8a6a18353ce2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5091504bd2fc95a74f2f0430b76a2dd029f26c3c514ecf0a1a47e8262bc21374e27786fc4f3b734c79df075d2c33794db90f3c31c5e20d45e7c10ebf99e70eec
|
|
7
|
+
data.tar.gz: 67fd93e9b4b45e0155d3cb1f9165f31810571d9eac1468e0bdbbfcf8429dc9089335961b7004bafa28176e2297602dbec7fcd4abdc794c15ffd5acb0f8ab024c
|
data/README.md
CHANGED
|
@@ -36,8 +36,6 @@ Emb.setup(host: "localhost", port: 6379)
|
|
|
36
36
|
Emb.setup
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
`Emb.config` is an alias for `Emb.setup`.
|
|
40
|
-
|
|
41
39
|
### Configuration sources (priority order)
|
|
42
40
|
|
|
43
41
|
1. Explicit `url:` or `host:`/`port:` arguments
|
|
@@ -160,7 +158,7 @@ Emb.setup
|
|
|
160
158
|
Emb[:minilm]["hello"] # proxy access
|
|
161
159
|
Emb.models # list models
|
|
162
160
|
Emb.info(:minilm) # model info
|
|
163
|
-
Emb.stats # server stats
|
|
161
|
+
Emb.stats # server stats (Hash of key => value)
|
|
164
162
|
Emb.help # command reference
|
|
165
163
|
Emb.ping # health check
|
|
166
164
|
```
|
|
@@ -169,6 +167,67 @@ These all delegate to a lazily-initialized default client. No explicit `setup` c
|
|
|
169
167
|
is required for simple cases — the default client connects to `redis://localhost:6379`
|
|
170
168
|
automatically.
|
|
171
169
|
|
|
170
|
+
## Server info & config
|
|
171
|
+
|
|
172
|
+
The server exposes Redis-style `INFO` and `CONFIG` commands; the gem wraps them.
|
|
173
|
+
|
|
174
|
+
### `Emb.stats` — server statistics as a hash
|
|
175
|
+
|
|
176
|
+
`EMB.STATS` is decoded into a Symbol-keyed Hash with values as the server sent them
|
|
177
|
+
(RESP integers stay Integer, everything else String):
|
|
178
|
+
|
|
179
|
+
```ruby
|
|
180
|
+
Emb.stats
|
|
181
|
+
# => {uptime_secs: 3, total_requests: 0, active_requests: "0", total_tokens: 0,
|
|
182
|
+
# total_errors: 0, models_loaded: 1, per_model: "minilm: req=0 avg=0us tok=0 ...",
|
|
183
|
+
# cache_hits: 0, cache_misses: 0, cache_evictions: 0}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
> **Breaking change (gem ≥ next release):** `Emb.stats` used to return the raw
|
|
187
|
+
> RESP array (`["uptime_secs", 3, "total_requests", 0, ...]`). It now returns the
|
|
188
|
+
> Hash above. Callers using `stats.each_slice(2)` or array indexing must migrate.
|
|
189
|
+
|
|
190
|
+
### `Emb.server_info` — sectioned INFO, parsed
|
|
191
|
+
|
|
192
|
+
The Redis-style `INFO` reply is parsed into a nested Hash. **No arguments = all
|
|
193
|
+
sections**; pass section names to filter (`:server`, `:cache`, `:keyspace`, `:stats`, `:clients`):
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
Emb.server_info
|
|
197
|
+
# => {Server: {redis_version: "0.2.4", emb_version: "0.2.4", uptime_secs: "7", ...},
|
|
198
|
+
# Cache: {cache_hits: 0, cache_misses: 0, cache_hit_rate: "0.0%", ...},
|
|
199
|
+
# Keyspace: {db0: "model=minilm,keys=0,hits=0,misses=0,hit_rate=0.0%"}, ...}
|
|
200
|
+
|
|
201
|
+
Emb.server_info(:server, :cache) # only those two sections
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### `Emb.config` — hot config read & change
|
|
205
|
+
|
|
206
|
+
`Emb.config` is a Hash-like live view of the server's runtime configuration
|
|
207
|
+
(backed by `CONFIG GET` / `CONFIG SET`). **Note:** the former `Emb.config` alias
|
|
208
|
+
for `Emb.setup` is gone — use `Emb.setup` to configure the client.
|
|
209
|
+
|
|
210
|
+
```ruby
|
|
211
|
+
Emb.config.to_h # all parameters
|
|
212
|
+
# => {"cache" => "auto", "cache_file" => "", "cache_save" => "", "listen" => ":6379",
|
|
213
|
+
# "password" => "", "models" => "minilm,bge", "tls_cert" => "", "tls_key" => ""}
|
|
214
|
+
|
|
215
|
+
Emb.config['cache'] # exact key => String value
|
|
216
|
+
# => "auto"
|
|
217
|
+
Emb.config['cache*'] # glob => Hash of matching parameters
|
|
218
|
+
Emb.config['listen'] # unknown key => nil
|
|
219
|
+
|
|
220
|
+
Emb.config['cache'] = '100MB' # live change; returns "OK"
|
|
221
|
+
Emb.config['cache_file'] = '/var/lib/emb/cache.rdb'
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Values are Strings (config is text, not metrics) and round-trip into writers
|
|
225
|
+
unchanged. `cache` resizes immediately, `cache_file`/`cache_save` apply at the
|
|
226
|
+
next snapshot save, `password` affects new connections. Errors surface as
|
|
227
|
+
exceptions (`RedisClient::CommandError`): read-only parameters (`listen`, `tls_*`,
|
|
228
|
+
`models`), invalid values, and `NOAUTH` on password-protected servers are not
|
|
229
|
+
swallowed.
|
|
230
|
+
|
|
172
231
|
## Usage
|
|
173
232
|
|
|
174
233
|
### Single text
|
data/lib/emb/client.rb
CHANGED
|
@@ -5,6 +5,8 @@ require 'redis_client'
|
|
|
5
5
|
|
|
6
6
|
module Emb
|
|
7
7
|
class Client
|
|
8
|
+
include Commands
|
|
9
|
+
|
|
8
10
|
attr_reader :pool
|
|
9
11
|
|
|
10
12
|
def initialize(pool: nil, batch: nil, **redis_options)
|
|
@@ -45,6 +47,11 @@ module Emb
|
|
|
45
47
|
@batch_enabled
|
|
46
48
|
end
|
|
47
49
|
|
|
50
|
+
# Live view of the server's runtime configuration (CONFIG GET/SET).
|
|
51
|
+
def config
|
|
52
|
+
@config ||= RuntimeConfig.new(self)
|
|
53
|
+
end
|
|
54
|
+
|
|
48
55
|
def models
|
|
49
56
|
raw = send_command('EMB.MODELS')
|
|
50
57
|
return [] if raw.nil?
|
|
@@ -63,8 +70,6 @@ module Emb
|
|
|
63
70
|
.to_h { |k, v| [k.to_sym, v] }
|
|
64
71
|
end
|
|
65
72
|
|
|
66
|
-
def stats = send_command('EMB.STATS')
|
|
67
|
-
|
|
68
73
|
def help = send_command('EMB.HELP')
|
|
69
74
|
|
|
70
75
|
def ping = send_command('PING')
|
data/lib/emb/commands.rb
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emb
|
|
4
|
+
# Server-status and runtime-config command wrappers. They only depend on
|
|
5
|
+
# #send_command, so they live in this module (included into Emb::Client)
|
|
6
|
+
# rather than growing the client class.
|
|
7
|
+
module Commands
|
|
8
|
+
# EMB.STATS as a Symbol-keyed Hash. No client-side type layer: values are
|
|
9
|
+
# exactly what the RESP decoder returned (Integer where the server sends
|
|
10
|
+
# RESP integers, String otherwise).
|
|
11
|
+
def stats
|
|
12
|
+
raw = send_command('EMB.STATS')
|
|
13
|
+
raw.each_slice(2).to_h { |key, value| [key.to_sym, value] }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Server-wide INFO (the Redis-style sectioned command). No sections =
|
|
17
|
+
# all sections; any number of sections filter the reply.
|
|
18
|
+
def server_info(*sections)
|
|
19
|
+
parse_info(send_command('INFO', *sections.map(&:to_s)))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
# Parse Redis INFO section text into a nested Hash:
|
|
25
|
+
# {Server: {redis_version: "0.2.4", uptime_secs: "7"}, Cache: {…}, …}
|
|
26
|
+
# Section names and keys are Symbols; values pass through as the server
|
|
27
|
+
# sent them. Lines that don't fit the grammar are ignored.
|
|
28
|
+
def parse_info(text)
|
|
29
|
+
sections = {}
|
|
30
|
+
current = nil
|
|
31
|
+
|
|
32
|
+
text.split("\r\n").each do |line|
|
|
33
|
+
if line.start_with?('# ')
|
|
34
|
+
current = line[2..].to_sym
|
|
35
|
+
sections[current] ||= {}
|
|
36
|
+
elsif current && line.include?(':')
|
|
37
|
+
key, value = line.split(':', 2)
|
|
38
|
+
sections[current][key.to_sym] = value
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
sections
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Emb
|
|
4
|
+
# Hash-like live view of the server's runtime configuration, backed by
|
|
5
|
+
# CONFIG GET / CONFIG SET.
|
|
6
|
+
#
|
|
7
|
+
# config.to_h # => { "cache" => "auto", "listen" => ":6379", … }
|
|
8
|
+
# config['cache'] # => "auto" (scalar for an exact key)
|
|
9
|
+
# config['cache*'] # => { "cache" => …, "cache_file" => … } (glob)
|
|
10
|
+
# config['cache_file'] = '/var/lib/emb/cache.rdb' # => "OK"
|
|
11
|
+
#
|
|
12
|
+
# Values are Strings (config is text, not metrics) and round-trip into
|
|
13
|
+
# writers unchanged. Server errors (unknown/read-only parameter, invalid
|
|
14
|
+
# value, NOAUTH) raise RedisClient::CommandError.
|
|
15
|
+
class RuntimeConfig
|
|
16
|
+
def initialize(client)
|
|
17
|
+
@client = client
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# All parameters as a String-keyed Hash (CONFIG GET).
|
|
21
|
+
def to_h
|
|
22
|
+
pairs(@client.send_command('CONFIG', 'GET'))
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Read one parameter or a glob. An exact key returns its String value
|
|
26
|
+
# (nil when the server has no such parameter); a glob that matches
|
|
27
|
+
# several parameters returns a Hash.
|
|
28
|
+
def [](key)
|
|
29
|
+
key = key.to_s
|
|
30
|
+
map = pairs(@client.send_command('CONFIG', 'GET', key))
|
|
31
|
+
return map[key] if map.key?(key)
|
|
32
|
+
|
|
33
|
+
map.empty? ? nil : map
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Write one parameter (CONFIG SET). Returns the server's reply ("OK").
|
|
37
|
+
def []=(key, value)
|
|
38
|
+
@client.send_command('CONFIG', 'SET', key.to_s, value.to_s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def pairs(raw)
|
|
44
|
+
raw.each_slice(2).to_h { |k, v| [k, v] }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
data/lib/emb.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'emb/version'
|
|
4
4
|
require_relative 'emb/configuration'
|
|
5
|
+
require_relative 'emb/commands'
|
|
6
|
+
require_relative 'emb/runtime_config'
|
|
5
7
|
require_relative 'emb/client'
|
|
6
8
|
require_relative 'emb/proxy'
|
|
7
9
|
require_relative 'emb/multi'
|
|
@@ -16,8 +18,6 @@ module Emb
|
|
|
16
18
|
@default_client = Client.new(...)
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
alias config setup
|
|
20
|
-
|
|
21
21
|
def configuration
|
|
22
22
|
@configuration ||= Configuration.new
|
|
23
23
|
end
|
|
@@ -32,6 +32,8 @@ module Emb
|
|
|
32
32
|
def models = default_client.models
|
|
33
33
|
def info(name) = default_client.info(name)
|
|
34
34
|
def stats = default_client.stats
|
|
35
|
+
def server_info(*sections) = default_client.server_info(*sections)
|
|
36
|
+
def config = default_client.config
|
|
35
37
|
def help = default_client.help
|
|
36
38
|
def ping = default_client.ping
|
|
37
39
|
def ready = default_client.ready
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: emb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- elcuervo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: batch-loader
|
|
@@ -64,10 +64,12 @@ files:
|
|
|
64
64
|
- lib/emb.rb
|
|
65
65
|
- lib/emb/batch.rb
|
|
66
66
|
- lib/emb/client.rb
|
|
67
|
+
- lib/emb/commands.rb
|
|
67
68
|
- lib/emb/configuration.rb
|
|
68
69
|
- lib/emb/middleware.rb
|
|
69
70
|
- lib/emb/multi.rb
|
|
70
71
|
- lib/emb/proxy.rb
|
|
72
|
+
- lib/emb/runtime_config.rb
|
|
71
73
|
- lib/emb/version.rb
|
|
72
74
|
homepage: https://github.com/elcuervo/emb
|
|
73
75
|
licenses:
|