mudis 0.8.0 → 0.8.1
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 +952 -932
- data/lib/mudis/version.rb +3 -3
- data/lib/mudis.rb +640 -631
- data/lib/mudis_client.rb +65 -65
- data/lib/mudis_config.rb +35 -35
- data/lib/mudis_proxy.rb +37 -37
- data/lib/mudis_server.rb +81 -81
- data/sig/mudis.rbs +56 -56
- data/sig/mudis_client.rbs +22 -22
- data/sig/mudis_config.rbs +10 -10
- data/sig/mudis_server.rbs +6 -6
- data/spec/eviction_spec.rb +29 -29
- data/spec/guardrails_spec.rb +138 -138
- data/spec/memory_guard_spec.rb +33 -33
- data/spec/metrics_spec.rb +34 -34
- data/spec/mudis_client_spec.rb +137 -137
- data/spec/mudis_server_spec.rb +94 -90
- data/spec/mudis_spec.rb +183 -183
- data/spec/namespace_spec.rb +69 -69
- data/spec/persistence_spec.rb +38 -37
- data/spec/reset_spec.rb +31 -31
- metadata +7 -3
data/lib/mudis_client.rb
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "socket"
|
|
4
|
-
require "json"
|
|
5
|
-
|
|
6
|
-
# thread-safe client for communicating with the MudisServer via UNIX socket.
|
|
7
|
-
class MudisClient
|
|
8
|
-
SOCKET_PATH = "/tmp/mudis.sock"
|
|
9
|
-
|
|
10
|
-
def initialize
|
|
11
|
-
@mutex = Mutex.new
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def request(payload) # rubocop:disable Metrics/MethodLength
|
|
15
|
-
@mutex.synchronize do
|
|
16
|
-
UNIXSocket.open(SOCKET_PATH) do |sock|
|
|
17
|
-
sock.puts(JSON.dump(payload))
|
|
18
|
-
response = sock.gets
|
|
19
|
-
res = JSON.parse(response, symbolize_names: true)
|
|
20
|
-
raise res[:error] unless res[:ok] # rubocop:disable Layout/EmptyLineAfterGuardClause
|
|
21
|
-
res[:value]
|
|
22
|
-
end
|
|
23
|
-
rescue Errno::ENOENT
|
|
24
|
-
warn "[MudisClient] Socket missing; master likely not running MudisServer"
|
|
25
|
-
nil
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def read(key, namespace: nil)
|
|
30
|
-
request(cmd: "read", key: key, namespace: namespace)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def write(key, value, expires_in: nil, namespace: nil)
|
|
34
|
-
request(cmd: "write", key: key, value: value, ttl: expires_in, namespace: namespace)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def delete(key, namespace: nil)
|
|
38
|
-
request(cmd: "delete", key: key, namespace: namespace)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def exists?(key, namespace: nil)
|
|
42
|
-
request(cmd: "exists", key: key, namespace: namespace)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def fetch(key, expires_in: nil, namespace: nil)
|
|
46
|
-
val = read(key, namespace: namespace)
|
|
47
|
-
return val if val
|
|
48
|
-
|
|
49
|
-
new_val = yield
|
|
50
|
-
write(key, new_val, expires_in: expires_in, namespace: namespace)
|
|
51
|
-
new_val
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def metrics
|
|
55
|
-
request(cmd: "metrics")
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def reset_metrics!
|
|
59
|
-
request(cmd: "reset_metrics")
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def reset!
|
|
63
|
-
request(cmd: "reset")
|
|
64
|
-
end
|
|
65
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
# thread-safe client for communicating with the MudisServer via UNIX socket.
|
|
7
|
+
class MudisClient
|
|
8
|
+
SOCKET_PATH = "/tmp/mudis.sock"
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@mutex = Mutex.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def request(payload) # rubocop:disable Metrics/MethodLength
|
|
15
|
+
@mutex.synchronize do
|
|
16
|
+
UNIXSocket.open(SOCKET_PATH) do |sock|
|
|
17
|
+
sock.puts(JSON.dump(payload))
|
|
18
|
+
response = sock.gets
|
|
19
|
+
res = JSON.parse(response, symbolize_names: true)
|
|
20
|
+
raise res[:error] unless res[:ok] # rubocop:disable Layout/EmptyLineAfterGuardClause
|
|
21
|
+
res[:value]
|
|
22
|
+
end
|
|
23
|
+
rescue Errno::ENOENT
|
|
24
|
+
warn "[MudisClient] Socket missing; master likely not running MudisServer"
|
|
25
|
+
nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def read(key, namespace: nil)
|
|
30
|
+
request(cmd: "read", key: key, namespace: namespace)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def write(key, value, expires_in: nil, namespace: nil)
|
|
34
|
+
request(cmd: "write", key: key, value: value, ttl: expires_in, namespace: namespace)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def delete(key, namespace: nil)
|
|
38
|
+
request(cmd: "delete", key: key, namespace: namespace)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def exists?(key, namespace: nil)
|
|
42
|
+
request(cmd: "exists", key: key, namespace: namespace)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def fetch(key, expires_in: nil, namespace: nil)
|
|
46
|
+
val = read(key, namespace: namespace)
|
|
47
|
+
return val if val
|
|
48
|
+
|
|
49
|
+
new_val = yield
|
|
50
|
+
write(key, new_val, expires_in: expires_in, namespace: namespace)
|
|
51
|
+
new_val
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def metrics
|
|
55
|
+
request(cmd: "metrics")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def reset_metrics!
|
|
59
|
+
request(cmd: "reset_metrics")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def reset!
|
|
63
|
+
request(cmd: "reset")
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/mudis_config.rb
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# MudisConfig holds all configuration values for Mudis,
|
|
4
|
-
# and provides defaults that can be overridden via Mudis.configure.
|
|
5
|
-
class MudisConfig
|
|
6
|
-
attr_accessor :serializer,
|
|
7
|
-
:compress,
|
|
8
|
-
:max_value_bytes,
|
|
9
|
-
:hard_memory_limit,
|
|
10
|
-
:max_bytes,
|
|
11
|
-
:buckets,
|
|
12
|
-
:max_ttl,
|
|
13
|
-
:default_ttl,
|
|
14
|
-
# Persistence settings
|
|
15
|
-
:persistence_enabled,
|
|
16
|
-
:persistence_path,
|
|
17
|
-
:persistence_format,
|
|
18
|
-
:persistence_safe_write
|
|
19
|
-
|
|
20
|
-
def initialize
|
|
21
|
-
@serializer = JSON # Default serialization strategy
|
|
22
|
-
@compress = false # Whether to compress values with Zlib
|
|
23
|
-
@max_value_bytes = nil # Max size per value (optional)
|
|
24
|
-
@hard_memory_limit = false # Enforce max_bytes as hard cap
|
|
25
|
-
@max_bytes = 1_073_741_824 # 1 GB default max cache size
|
|
26
|
-
@buckets = nil # use nil to signal fallback to ENV or default
|
|
27
|
-
@max_ttl = nil # Max TTL for cache entries (optional)
|
|
28
|
-
@default_ttl = nil # Default TTL for cache entries (optional)
|
|
29
|
-
# Persistence settings
|
|
30
|
-
@persistence_enabled = false # Whether persistence is enabled
|
|
31
|
-
@persistence_path =
|
|
32
|
-
@persistence_format = :json # Default persistence file format
|
|
33
|
-
@persistence_safe_write = true # Whether to use safe write for persistence
|
|
34
|
-
end
|
|
35
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# MudisConfig holds all configuration values for Mudis,
|
|
4
|
+
# and provides defaults that can be overridden via Mudis.configure.
|
|
5
|
+
class MudisConfig
|
|
6
|
+
attr_accessor :serializer,
|
|
7
|
+
:compress,
|
|
8
|
+
:max_value_bytes,
|
|
9
|
+
:hard_memory_limit,
|
|
10
|
+
:max_bytes,
|
|
11
|
+
:buckets,
|
|
12
|
+
:max_ttl,
|
|
13
|
+
:default_ttl,
|
|
14
|
+
# Persistence settings
|
|
15
|
+
:persistence_enabled,
|
|
16
|
+
:persistence_path,
|
|
17
|
+
:persistence_format,
|
|
18
|
+
:persistence_safe_write
|
|
19
|
+
|
|
20
|
+
def initialize # rubocop:disable Metrics/MethodLength
|
|
21
|
+
@serializer = JSON # Default serialization strategy
|
|
22
|
+
@compress = false # Whether to compress values with Zlib
|
|
23
|
+
@max_value_bytes = nil # Max size per value (optional)
|
|
24
|
+
@hard_memory_limit = false # Enforce max_bytes as hard cap
|
|
25
|
+
@max_bytes = 1_073_741_824 # 1 GB default max cache size
|
|
26
|
+
@buckets = nil # use nil to signal fallback to ENV or default
|
|
27
|
+
@max_ttl = nil # Max TTL for cache entries (optional)
|
|
28
|
+
@default_ttl = nil # Default TTL for cache entries (optional)
|
|
29
|
+
# Persistence settings
|
|
30
|
+
@persistence_enabled = false # Whether persistence is enabled
|
|
31
|
+
@persistence_path = "mudis_data" # Default path for persistence files
|
|
32
|
+
@persistence_format = :json # Default persistence file format
|
|
33
|
+
@persistence_safe_write = true # Whether to use safe write for persistence
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/mudis_proxy.rb
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Optional Mudis proxy layer for IPC mode.
|
|
4
|
-
#
|
|
5
|
-
# To enable:
|
|
6
|
-
# require "mudis_proxy"
|
|
7
|
-
#
|
|
8
|
-
# The proxy will forward calls to `$mudis` (an instance of MudisClient)
|
|
9
|
-
# if it is defined, otherwise fallback to standard in-process behaviour.
|
|
10
|
-
|
|
11
|
-
require_relative "mudis"
|
|
12
|
-
require_relative "mudis_client"
|
|
13
|
-
|
|
14
|
-
# Note that this file must be required after MudisServer
|
|
15
|
-
# has been loaded, otherwise the proxy will not be activated.
|
|
16
|
-
|
|
17
|
-
unless defined?(MudisClient)
|
|
18
|
-
warn "[MudisProxy] MudisClient not loaded: proxy not activated"
|
|
19
|
-
return
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
unless defined?($mudis) && $mudis # rubocop:disable Style/GlobalVars
|
|
23
|
-
warn "[MudisProxy] $mudis not set: proxy not activated"
|
|
24
|
-
return
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class << Mudis
|
|
28
|
-
def read(*a, **k) = $mudis.read(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
29
|
-
def write(*a, **k) = $mudis.write(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
30
|
-
def delete(*a, **k) = $mudis.delete(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
31
|
-
def fetch(*a, **k, &b) = $mudis.fetch(*a, **k, &b) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
32
|
-
def metrics = $mudis.metrics # rubocop:disable Style/GlobalVars
|
|
33
|
-
def reset_metrics! = $mudis.reset_metrics! # rubocop:disable Style/GlobalVars
|
|
34
|
-
def reset! = $mudis.reset! # rubocop:disable Style/GlobalVars
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
warn "[MudisProxy] Proxy activated: forwarding calls to $mudis"
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Optional Mudis proxy layer for IPC mode.
|
|
4
|
+
#
|
|
5
|
+
# To enable:
|
|
6
|
+
# require "mudis_proxy"
|
|
7
|
+
#
|
|
8
|
+
# The proxy will forward calls to `$mudis` (an instance of MudisClient)
|
|
9
|
+
# if it is defined, otherwise fallback to standard in-process behaviour.
|
|
10
|
+
|
|
11
|
+
require_relative "mudis"
|
|
12
|
+
require_relative "mudis_client"
|
|
13
|
+
|
|
14
|
+
# Note that this file must be required after MudisServer
|
|
15
|
+
# has been loaded, otherwise the proxy will not be activated.
|
|
16
|
+
|
|
17
|
+
unless defined?(MudisClient)
|
|
18
|
+
warn "[MudisProxy] MudisClient not loaded: proxy not activated"
|
|
19
|
+
return
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
unless defined?($mudis) && $mudis # rubocop:disable Style/GlobalVars
|
|
23
|
+
warn "[MudisProxy] $mudis not set: proxy not activated"
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class << Mudis
|
|
28
|
+
def read(*a, **k) = $mudis.read(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
29
|
+
def write(*a, **k) = $mudis.write(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
30
|
+
def delete(*a, **k) = $mudis.delete(*a, **k) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
31
|
+
def fetch(*a, **k, &b) = $mudis.fetch(*a, **k, &b) # rubocop:disable Naming/MethodParameterName,Style/GlobalVars
|
|
32
|
+
def metrics = $mudis.metrics # rubocop:disable Style/GlobalVars
|
|
33
|
+
def reset_metrics! = $mudis.reset_metrics! # rubocop:disable Style/GlobalVars
|
|
34
|
+
def reset! = $mudis.reset! # rubocop:disable Style/GlobalVars
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
warn "[MudisProxy] Proxy activated: forwarding calls to $mudis"
|
data/lib/mudis_server.rb
CHANGED
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "socket"
|
|
4
|
-
require "json"
|
|
5
|
-
require_relative "mudis"
|
|
6
|
-
|
|
7
|
-
# Simple UNIX socket server for handling Mudis operations via IPC mode
|
|
8
|
-
class MudisServer
|
|
9
|
-
SOCKET_PATH = "/tmp/mudis.sock"
|
|
10
|
-
|
|
11
|
-
def self.start! # rubocop:disable Metrics/MethodLength
|
|
12
|
-
# Clean up old socket if it exists
|
|
13
|
-
File.unlink(SOCKET_PATH) if File.exist?(SOCKET_PATH)
|
|
14
|
-
|
|
15
|
-
server = UNIXServer.new(SOCKET_PATH)
|
|
16
|
-
server.listen(128)
|
|
17
|
-
puts "[MudisServer] Listening on #{SOCKET_PATH}"
|
|
18
|
-
|
|
19
|
-
Thread.new do
|
|
20
|
-
loop do
|
|
21
|
-
client = server.accept
|
|
22
|
-
Thread.new(client) do |sock|
|
|
23
|
-
handle_client(sock)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def self.handle_client(sock) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/MethodLength
|
|
30
|
-
request_line = sock.gets
|
|
31
|
-
return unless request_line
|
|
32
|
-
|
|
33
|
-
req = JSON.parse(request_line, symbolize_names: true)
|
|
34
|
-
cmd = req[:cmd]
|
|
35
|
-
key = req[:key]
|
|
36
|
-
ns = req[:namespace]
|
|
37
|
-
val = req[:value]
|
|
38
|
-
ttl = req[:ttl]
|
|
39
|
-
|
|
40
|
-
begin
|
|
41
|
-
case cmd
|
|
42
|
-
when "read"
|
|
43
|
-
result = Mudis.read(key, namespace: ns)
|
|
44
|
-
sock.puts(JSON.dump({ ok: true, value: result }))
|
|
45
|
-
|
|
46
|
-
when "write"
|
|
47
|
-
Mudis.write(key, val, expires_in: ttl, namespace: ns)
|
|
48
|
-
sock.puts(JSON.dump({ ok: true }))
|
|
49
|
-
|
|
50
|
-
when "delete"
|
|
51
|
-
Mudis.delete(key, namespace: ns)
|
|
52
|
-
sock.puts(JSON.dump({ ok: true }))
|
|
53
|
-
|
|
54
|
-
when "exists"
|
|
55
|
-
sock.puts(JSON.dump({ ok: true, value: Mudis.exists?(key, namespace: ns) }))
|
|
56
|
-
|
|
57
|
-
when "fetch"
|
|
58
|
-
result = Mudis.fetch(key, expires_in: ttl, namespace: ns) { req[:fallback] }
|
|
59
|
-
sock.puts(JSON.dump({ ok: true, value: result }))
|
|
60
|
-
|
|
61
|
-
when "metrics"
|
|
62
|
-
sock.puts(JSON.dump({ ok: true, value: Mudis.metrics }))
|
|
63
|
-
|
|
64
|
-
when "reset_metrics"
|
|
65
|
-
Mudis.reset_metrics!
|
|
66
|
-
sock.puts(JSON.dump({ ok: true }))
|
|
67
|
-
|
|
68
|
-
when "reset"
|
|
69
|
-
Mudis.reset!
|
|
70
|
-
sock.puts(JSON.dump({ ok: true }))
|
|
71
|
-
|
|
72
|
-
else
|
|
73
|
-
sock.puts(JSON.dump({ ok: false, error: "unknown command: #{cmd}" }))
|
|
74
|
-
end
|
|
75
|
-
rescue StandardError => e
|
|
76
|
-
sock.puts(JSON.dump({ ok: false, error: e.message }))
|
|
77
|
-
ensure
|
|
78
|
-
sock.close
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
require "json"
|
|
5
|
+
require_relative "mudis"
|
|
6
|
+
|
|
7
|
+
# Simple UNIX socket server for handling Mudis operations via IPC mode
|
|
8
|
+
class MudisServer
|
|
9
|
+
SOCKET_PATH = "/tmp/mudis.sock"
|
|
10
|
+
|
|
11
|
+
def self.start! # rubocop:disable Metrics/MethodLength
|
|
12
|
+
# Clean up old socket if it exists
|
|
13
|
+
File.unlink(SOCKET_PATH) if File.exist?(SOCKET_PATH)
|
|
14
|
+
|
|
15
|
+
server = UNIXServer.new(SOCKET_PATH)
|
|
16
|
+
server.listen(128)
|
|
17
|
+
puts "[MudisServer] Listening on #{SOCKET_PATH}"
|
|
18
|
+
|
|
19
|
+
Thread.new do
|
|
20
|
+
loop do
|
|
21
|
+
client = server.accept
|
|
22
|
+
Thread.new(client) do |sock|
|
|
23
|
+
handle_client(sock)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.handle_client(sock) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/MethodLength
|
|
30
|
+
request_line = sock.gets
|
|
31
|
+
return unless request_line
|
|
32
|
+
|
|
33
|
+
req = JSON.parse(request_line, symbolize_names: true)
|
|
34
|
+
cmd = req[:cmd]
|
|
35
|
+
key = req[:key]
|
|
36
|
+
ns = req[:namespace]
|
|
37
|
+
val = req[:value]
|
|
38
|
+
ttl = req[:ttl]
|
|
39
|
+
|
|
40
|
+
begin
|
|
41
|
+
case cmd
|
|
42
|
+
when "read"
|
|
43
|
+
result = Mudis.read(key, namespace: ns)
|
|
44
|
+
sock.puts(JSON.dump({ ok: true, value: result }))
|
|
45
|
+
|
|
46
|
+
when "write"
|
|
47
|
+
Mudis.write(key, val, expires_in: ttl, namespace: ns)
|
|
48
|
+
sock.puts(JSON.dump({ ok: true }))
|
|
49
|
+
|
|
50
|
+
when "delete"
|
|
51
|
+
Mudis.delete(key, namespace: ns)
|
|
52
|
+
sock.puts(JSON.dump({ ok: true }))
|
|
53
|
+
|
|
54
|
+
when "exists"
|
|
55
|
+
sock.puts(JSON.dump({ ok: true, value: Mudis.exists?(key, namespace: ns) }))
|
|
56
|
+
|
|
57
|
+
when "fetch"
|
|
58
|
+
result = Mudis.fetch(key, expires_in: ttl, namespace: ns) { req[:fallback] }
|
|
59
|
+
sock.puts(JSON.dump({ ok: true, value: result }))
|
|
60
|
+
|
|
61
|
+
when "metrics"
|
|
62
|
+
sock.puts(JSON.dump({ ok: true, value: Mudis.metrics }))
|
|
63
|
+
|
|
64
|
+
when "reset_metrics"
|
|
65
|
+
Mudis.reset_metrics!
|
|
66
|
+
sock.puts(JSON.dump({ ok: true }))
|
|
67
|
+
|
|
68
|
+
when "reset"
|
|
69
|
+
Mudis.reset!
|
|
70
|
+
sock.puts(JSON.dump({ ok: true }))
|
|
71
|
+
|
|
72
|
+
else
|
|
73
|
+
sock.puts(JSON.dump({ ok: false, error: "unknown command: #{cmd}" }))
|
|
74
|
+
end
|
|
75
|
+
rescue StandardError => e
|
|
76
|
+
sock.puts(JSON.dump({ ok: false, error: e.message }))
|
|
77
|
+
ensure
|
|
78
|
+
sock.close
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
data/sig/mudis.rbs
CHANGED
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
class Mudis
|
|
2
|
-
# Configuration
|
|
3
|
-
class << self
|
|
4
|
-
attr_accessor serializer : Object
|
|
5
|
-
attr_accessor compress : bool
|
|
6
|
-
attr_accessor hard_memory_limit : bool
|
|
7
|
-
attr_reader max_bytes : Integer
|
|
8
|
-
attr_reader max_value_bytes : Integer?
|
|
9
|
-
attr_accessor max_ttl: Integer?
|
|
10
|
-
attr_accessor default_ttl: Integer?
|
|
11
|
-
|
|
12
|
-
def configure: () { (config: MudisConfig) -> void } -> void
|
|
13
|
-
def config: () -> MudisConfig
|
|
14
|
-
def apply_config!: () -> void
|
|
15
|
-
def validate_config!: () -> void
|
|
16
|
-
|
|
17
|
-
def buckets: () -> Integer
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Lifecycle
|
|
21
|
-
def self.start_expiry_thread: (?interval: Integer) -> void
|
|
22
|
-
def self.stop_expiry_thread: () -> void
|
|
23
|
-
|
|
24
|
-
# Core operations
|
|
25
|
-
def self.write: (String, untyped, ?expires_in: Integer, ?namespace: String) -> void
|
|
26
|
-
def self.read: (String, ?namespace: String) -> untyped?
|
|
27
|
-
def self.update: (String, ?namespace: String) { (untyped) -> untyped } -> void
|
|
28
|
-
def self.delete: (String, ?namespace: String) -> void
|
|
29
|
-
def self.exists?: (String, ?namespace: String) -> bool
|
|
30
|
-
|
|
31
|
-
# DSL & Helpers
|
|
32
|
-
def self.fetch: (
|
|
33
|
-
String,
|
|
34
|
-
?expires_in: Integer,
|
|
35
|
-
?force: bool,
|
|
36
|
-
?namespace: String
|
|
37
|
-
) { () -> untyped } -> untyped
|
|
38
|
-
|
|
39
|
-
def self.clear: (String, ?namespace: String) -> void
|
|
40
|
-
def self.replace: (String, untyped, ?expires_in: Integer, ?namespace: String) -> void
|
|
41
|
-
def self.inspect: (String, ?namespace: String) -> Hash[Symbol, untyped]?
|
|
42
|
-
def self.keys: (?namespace: String) -> Array[String]
|
|
43
|
-
def self.clear_namespace: (?namespace: String) -> void
|
|
44
|
-
|
|
45
|
-
# Introspection & management
|
|
46
|
-
def self.metrics: () -> Hash[Symbol, untyped]
|
|
47
|
-
def self.cleanup_expired!: () -> void
|
|
48
|
-
def self.all_keys: () -> Array[String]
|
|
49
|
-
def self.current_memory_bytes: () -> Integer
|
|
50
|
-
def self.max_memory_bytes: () -> Integer
|
|
51
|
-
def self.least_touched: (?Integer) -> Array[[String, Integer]]
|
|
52
|
-
|
|
53
|
-
# State reset
|
|
54
|
-
def self.reset!: () -> void
|
|
55
|
-
def self.reset_metrics!: () -> void
|
|
56
|
-
end
|
|
1
|
+
class Mudis
|
|
2
|
+
# Configuration
|
|
3
|
+
class << self
|
|
4
|
+
attr_accessor serializer : Object
|
|
5
|
+
attr_accessor compress : bool
|
|
6
|
+
attr_accessor hard_memory_limit : bool
|
|
7
|
+
attr_reader max_bytes : Integer
|
|
8
|
+
attr_reader max_value_bytes : Integer?
|
|
9
|
+
attr_accessor max_ttl: Integer?
|
|
10
|
+
attr_accessor default_ttl: Integer?
|
|
11
|
+
|
|
12
|
+
def configure: () { (config: MudisConfig) -> void } -> void
|
|
13
|
+
def config: () -> MudisConfig
|
|
14
|
+
def apply_config!: () -> void
|
|
15
|
+
def validate_config!: () -> void
|
|
16
|
+
|
|
17
|
+
def buckets: () -> Integer
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Lifecycle
|
|
21
|
+
def self.start_expiry_thread: (?interval: Integer) -> void
|
|
22
|
+
def self.stop_expiry_thread: () -> void
|
|
23
|
+
|
|
24
|
+
# Core operations
|
|
25
|
+
def self.write: (String, untyped, ?expires_in: Integer, ?namespace: String) -> void
|
|
26
|
+
def self.read: (String, ?namespace: String) -> untyped?
|
|
27
|
+
def self.update: (String, ?namespace: String) { (untyped) -> untyped } -> void
|
|
28
|
+
def self.delete: (String, ?namespace: String) -> void
|
|
29
|
+
def self.exists?: (String, ?namespace: String) -> bool
|
|
30
|
+
|
|
31
|
+
# DSL & Helpers
|
|
32
|
+
def self.fetch: (
|
|
33
|
+
String,
|
|
34
|
+
?expires_in: Integer,
|
|
35
|
+
?force: bool,
|
|
36
|
+
?namespace: String
|
|
37
|
+
) { () -> untyped } -> untyped
|
|
38
|
+
|
|
39
|
+
def self.clear: (String, ?namespace: String) -> void
|
|
40
|
+
def self.replace: (String, untyped, ?expires_in: Integer, ?namespace: String) -> void
|
|
41
|
+
def self.inspect: (String, ?namespace: String) -> Hash[Symbol, untyped]?
|
|
42
|
+
def self.keys: (?namespace: String) -> Array[String]
|
|
43
|
+
def self.clear_namespace: (?namespace: String) -> void
|
|
44
|
+
|
|
45
|
+
# Introspection & management
|
|
46
|
+
def self.metrics: () -> Hash[Symbol, untyped]
|
|
47
|
+
def self.cleanup_expired!: () -> void
|
|
48
|
+
def self.all_keys: () -> Array[String]
|
|
49
|
+
def self.current_memory_bytes: () -> Integer
|
|
50
|
+
def self.max_memory_bytes: () -> Integer
|
|
51
|
+
def self.least_touched: (?Integer) -> Array[[String, Integer]]
|
|
52
|
+
|
|
53
|
+
# State reset
|
|
54
|
+
def self.reset!: () -> void
|
|
55
|
+
def self.reset_metrics!: () -> void
|
|
56
|
+
end
|
data/sig/mudis_client.rbs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
class MudisClient
|
|
2
|
-
SOCKET_PATH: String
|
|
3
|
-
|
|
4
|
-
def initialize: () -> void
|
|
5
|
-
|
|
6
|
-
def request: (payload: { cmd: String, key?: String, value?: untyped, ttl?: Integer?, namespace?: String? }) -> untyped
|
|
7
|
-
|
|
8
|
-
def read: (key: String, namespace?: String?) -> untyped
|
|
9
|
-
|
|
10
|
-
def write: (key: String, value: untyped, expires_in?: Integer?, namespace?: String?) -> untyped
|
|
11
|
-
|
|
12
|
-
def delete: (key: String, namespace?: String?) -> untyped
|
|
13
|
-
|
|
14
|
-
def exists?: (key: String, namespace?: String?) -> bool
|
|
15
|
-
|
|
16
|
-
def fetch: (key: String, expires_in?: Integer?, namespace?: String?, &block: { () -> untyped }) -> untyped
|
|
17
|
-
|
|
18
|
-
def metrics: () -> { reads: Integer, writes: Integer, deletes: Integer, exists: Integer }
|
|
19
|
-
|
|
20
|
-
def reset_metrics!: () -> void
|
|
21
|
-
|
|
22
|
-
def reset!: () -> void
|
|
1
|
+
class MudisClient
|
|
2
|
+
SOCKET_PATH: String
|
|
3
|
+
|
|
4
|
+
def initialize: () -> void
|
|
5
|
+
|
|
6
|
+
def request: (payload: { cmd: String, key?: String, value?: untyped, ttl?: Integer?, namespace?: String? }) -> untyped
|
|
7
|
+
|
|
8
|
+
def read: (key: String, namespace?: String?) -> untyped
|
|
9
|
+
|
|
10
|
+
def write: (key: String, value: untyped, expires_in?: Integer?, namespace?: String?) -> untyped
|
|
11
|
+
|
|
12
|
+
def delete: (key: String, namespace?: String?) -> untyped
|
|
13
|
+
|
|
14
|
+
def exists?: (key: String, namespace?: String?) -> bool
|
|
15
|
+
|
|
16
|
+
def fetch: (key: String, expires_in?: Integer?, namespace?: String?, &block: { () -> untyped }) -> untyped
|
|
17
|
+
|
|
18
|
+
def metrics: () -> { reads: Integer, writes: Integer, deletes: Integer, exists: Integer }
|
|
19
|
+
|
|
20
|
+
def reset_metrics!: () -> void
|
|
21
|
+
|
|
22
|
+
def reset!: () -> void
|
|
23
23
|
end
|
data/sig/mudis_config.rbs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
class MudisConfig
|
|
2
|
-
attr_accessor serializer: Object
|
|
3
|
-
attr_accessor compress: bool
|
|
4
|
-
attr_accessor max_value_bytes: Integer?
|
|
5
|
-
attr_accessor hard_memory_limit: bool
|
|
6
|
-
attr_accessor max_bytes: Integer
|
|
7
|
-
attr_accessor max_ttl: Integer?
|
|
8
|
-
attr_accessor default_ttl: Integer?
|
|
9
|
-
attr_accessor buckets: Integer?
|
|
10
|
-
end
|
|
1
|
+
class MudisConfig
|
|
2
|
+
attr_accessor serializer: Object
|
|
3
|
+
attr_accessor compress: bool
|
|
4
|
+
attr_accessor max_value_bytes: Integer?
|
|
5
|
+
attr_accessor hard_memory_limit: bool
|
|
6
|
+
attr_accessor max_bytes: Integer
|
|
7
|
+
attr_accessor max_ttl: Integer?
|
|
8
|
+
attr_accessor default_ttl: Integer?
|
|
9
|
+
attr_accessor buckets: Integer?
|
|
10
|
+
end
|
data/sig/mudis_server.rbs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
class MudisServer
|
|
2
|
-
SOCKET_PATH: String
|
|
3
|
-
|
|
4
|
-
def self.start!: () -> void
|
|
5
|
-
|
|
6
|
-
def self.handle_client: (sock: UNIXSocket) -> void
|
|
1
|
+
class MudisServer
|
|
2
|
+
SOCKET_PATH: String
|
|
3
|
+
|
|
4
|
+
def self.start!: () -> void
|
|
5
|
+
|
|
6
|
+
def self.handle_client: (sock: UNIXSocket) -> void
|
|
7
7
|
end
|