mudis 0.4.2 → 0.4.4
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 +175 -25
- data/lib/mudis/version.rb +1 -1
- data/lib/mudis.rb +32 -4
- data/lib/mudis_config.rb +3 -1
- data/sig/mudis.rbs +3 -2
- data/sig/mudis_config.rbs +1 -0
- data/spec/guardrails_spec.rb +58 -0
- metadata +23 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b180000138c976ee0e0c7a7cdc068550c5f33f39f363c63ba6397b84fe8f6cbe
|
4
|
+
data.tar.gz: ee6de323fd9dcc5914ec0fde68da5fff7289e6c830395b9d4be4271d389b2c15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7d2c14ca2b2dce8ed23f5fb371fe73456d92d9613e25d75fb645d1a6903259a21dd31dc7e3acca8f4336dc77990d5f33fce9254e3becdbcc59d7c19c526a302
|
7
|
+
data.tar.gz: 6619380f6d7206caec28c0e1f3f5450bb8991817fff6c08d6e7b5ceff2c82edc8a7c7b51b38894e5fb5a09e5f41a0546c50b951d088accfc1dc70a91935d398d
|
data/README.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|

|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/mudis)
|
3
|
+
[](https://badge.fury.io/rb/mudis)
|
4
4
|
|
5
5
|
**Mudis** is a fast, thread-safe, in-memory, sharded LRU (Least Recently Used) cache for Ruby applications. Inspired by Redis, it provides value serialization, optional compression, per-key expiry, and metric tracking in a lightweight, dependency-free package that lives inside your Ruby process.
|
6
6
|
|
7
7
|
It’s ideal for scenarios where performance and process-local caching are critical, and where a full Redis setup is overkill or otherwise not possible/desirable.
|
8
8
|
|
9
|
-
Alternatively, Mudis can be upscaled with higher sharding and resources in a dedicated Rails app to provide a Mudis server.
|
9
|
+
Alternatively, Mudis can be upscaled with higher sharding and resources in a dedicated Rails app to provide a [Mudis server](#create-a-mudis-server).
|
10
10
|
|
11
11
|
### Why another Caching Gem?
|
12
12
|
|
@@ -305,12 +305,12 @@ end
|
|
305
305
|
| `Mudis.serializer` | JSON, Marshal, or Oj | `JSON` |
|
306
306
|
| `Mudis.compress` | Enable Zlib compression | `false` |
|
307
307
|
| `Mudis.max_value_bytes` | Max allowed size in bytes for a value | `nil` (no limit) |
|
308
|
-
| `Mudis.buckets` | Number of cache shards
|
309
|
-
| `start_expiry_thread` | Background TTL cleanup loop (every N sec) | Disabled by default|
|
310
|
-
| `hard_memory_limit` | Enforce hard memory limits on key size and reject if exceeded | `false`|
|
311
|
-
| `max_bytes` | Maximum allowed cache size | `1GB`|
|
308
|
+
| `Mudis.buckets` | Number of cache shards | `32` |
|
309
|
+
| `Mudis.start_expiry_thread` | Background TTL cleanup loop (every N sec) | Disabled by default|
|
310
|
+
| `Mudis.hard_memory_limit` | Enforce hard memory limits on key size and reject if exceeded | `false`|
|
311
|
+
| `Mudis.max_bytes` | Maximum allowed cache size | `1GB`|
|
312
312
|
|
313
|
-
|
313
|
+
Buckets can also be set using a `MUDIS_BUCKETS` environment variable.
|
314
314
|
|
315
315
|
When setting `serializer`, be mindful of the below
|
316
316
|
|
@@ -320,21 +320,69 @@ When setting `serializer`, be mindful of the below
|
|
320
320
|
| `JSON` | Cross-language interoperability |
|
321
321
|
| `Oj` | API-heavy apps using JSON at scale |
|
322
322
|
|
323
|
-
|
323
|
+
---
|
324
|
+
|
325
|
+
## Benchmarks
|
326
|
+
|
327
|
+
#### Serializer(s)
|
324
328
|
|
325
|
-
|
329
|
+
_100000 iterations_
|
326
330
|
|
327
|
-
| Serializer |
|
328
|
-
|
329
|
-
| oj |
|
330
|
-
| marshal |
|
331
|
-
| json |
|
332
|
-
| oj + zlib |
|
333
|
-
| marshal + zlib |
|
334
|
-
| json + zlib |
|
331
|
+
| Serializer | Total Time (s) | Ops/sec |
|
332
|
+
|----------------|------------|----------------|
|
333
|
+
| oj | 0.1342 | 745320 |
|
334
|
+
| marshal | 0.3228 | 309824 |
|
335
|
+
| json | 0.9035 | 110682 |
|
336
|
+
| oj + zlib | 1.8050 | 55401 |
|
337
|
+
| marshal + zlib | 1.8057 | 55381 |
|
338
|
+
| json + zlib | 2.7949 | 35780 |
|
335
339
|
|
336
340
|
> If opting for OJ, you will need to install the dependency in your project and configure as needed.
|
337
341
|
|
342
|
+
#### Mudis vs Rails.cache
|
343
|
+
|
344
|
+
Mudis is marginally slower than `Rails.cache` by design; it trades raw speed for control, observability, and safety.
|
345
|
+
|
346
|
+
_10000 iterations of 1MB, Marshal (to match MemoryStore default), compression ON_
|
347
|
+
|
348
|
+
| Operation | `Rails.cache` | `Mudis` | Delta |
|
349
|
+
| --------- | ------------- | ----------- | --------- |
|
350
|
+
| Write | 2.139 ms/op | 2.417 ms/op | +0.278 ms |
|
351
|
+
| Read | 0.007 ms/op | 0.810 ms/op | +0.803 ms |
|
352
|
+
|
353
|
+
> For context: a typical database query or HTTP call takes 10–50ms. A difference of less than 1ms per operation is negligible for most apps.
|
354
|
+
|
355
|
+
###### **Why this overhead exists**
|
356
|
+
|
357
|
+
Mudis includes features that MemoryStore doesn’t:
|
358
|
+
|
359
|
+
| Feature | Mudis | Rails.cache (MemoryStore) |
|
360
|
+
| ------------------ | ---------------------- | --------------------------- |
|
361
|
+
| Per-key TTL expiry | ✅ | ⚠️ on access |
|
362
|
+
| True LRU eviction | ✅ | ❌ |
|
363
|
+
| Hard memory limits | ✅ | ❌ |
|
364
|
+
| Value compression | ✅ | ❌ |
|
365
|
+
| Thread safety | ✅ Bucket-level mutexes | ✅ Global mutex |
|
366
|
+
| Observability | ✅ | ❌ |
|
367
|
+
| Namespacing | ✅ | ❌ Manual scoping |
|
368
|
+
|
369
|
+
It will be down to the developer to decide if a fraction of a millisecond is worth
|
370
|
+
|
371
|
+
- Predictable eviction
|
372
|
+
- Configurable expiry
|
373
|
+
- Memory protection
|
374
|
+
- Namespace scoping
|
375
|
+
- Real-time metrics for hits, misses, evictions, memory usage
|
376
|
+
|
377
|
+
_10000 iterations of 1MB, Marshal (to match MemoryStore default), compression OFF (to match MemoryStore default)_
|
378
|
+
|
379
|
+
| Operation | `Rails.cache` | `Mudis` | Delta |
|
380
|
+
| --------- | ------------- | ----------- | ------------- |
|
381
|
+
| Write | 2.342 ms/op | 0.501 ms/op | **−1.841 ms** |
|
382
|
+
| Read | 0.007 ms/op | 0.011 ms/op | +0.004 ms |
|
383
|
+
|
384
|
+
With compression disabled, Mudis writes significanty faster and reads are virtually identical. Optimisation and configuration of Mudis will be determined by your individual needs.
|
385
|
+
|
338
386
|
---
|
339
387
|
|
340
388
|
## Graceful Shutdown
|
@@ -354,6 +402,115 @@ at_exit { Mudis.stop_expiry_thread }
|
|
354
402
|
|
355
403
|
---
|
356
404
|
|
405
|
+
## Create a Mudis Server
|
406
|
+
|
407
|
+
### Minimal Setup
|
408
|
+
|
409
|
+
- Create a new Rails API app:
|
410
|
+
|
411
|
+
```bash
|
412
|
+
rails new mudis-server --api
|
413
|
+
cd mudis-server
|
414
|
+
```
|
415
|
+
|
416
|
+
- Add mudis to your Gemfile
|
417
|
+
- Create Initializer: `config/initializers/mudis.rb`
|
418
|
+
- Define routes
|
419
|
+
|
420
|
+
```ruby
|
421
|
+
Rails.application.routes.draw do
|
422
|
+
get "/cache/:key", to: "cache#show"
|
423
|
+
post "/cache/:key", to: "cache#write"
|
424
|
+
delete "/cache/:key", to: "cache#delete"
|
425
|
+
get "/metrics", to: "cache#metrics"
|
426
|
+
end
|
427
|
+
```
|
428
|
+
|
429
|
+
- Create a `cache_controller` (with optional per caller/consumer namespace)
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
class CacheController < ApplicationController
|
433
|
+
|
434
|
+
def show
|
435
|
+
key = params[:key]
|
436
|
+
ns = params[:namespace]
|
437
|
+
|
438
|
+
value = Mudis.read(key, namespace: ns)
|
439
|
+
if value.nil?
|
440
|
+
render json: { error: "not found" }, status: :not_found
|
441
|
+
else
|
442
|
+
render json: { value: value }
|
443
|
+
end
|
444
|
+
end
|
445
|
+
|
446
|
+
def write
|
447
|
+
key = params[:key]
|
448
|
+
ns = params[:namespace]
|
449
|
+
val = params[:value]
|
450
|
+
ttl = params[:expires_in]&.to_i
|
451
|
+
|
452
|
+
Mudis.write(key, val, expires_in: ttl, namespace: ns)
|
453
|
+
render json: { status: "written", key: key }
|
454
|
+
end
|
455
|
+
|
456
|
+
def delete
|
457
|
+
key = params[:key]
|
458
|
+
ns = params[:namespace]
|
459
|
+
|
460
|
+
Mudis.delete(key, namespace: ns)
|
461
|
+
render json: { status: "deleted" }
|
462
|
+
end
|
463
|
+
|
464
|
+
def metrics
|
465
|
+
render json: Mudis.metrics
|
466
|
+
end
|
467
|
+
end
|
468
|
+
```
|
469
|
+
|
470
|
+
- Test it
|
471
|
+
|
472
|
+
```bash
|
473
|
+
curl http://localhost:3000/cache/foo
|
474
|
+
curl -X POST http://localhost:3000/cache/foo -d 'value=bar&expires_in=60'
|
475
|
+
curl http://localhost:3000/metrics
|
476
|
+
|
477
|
+
# Write with namespace
|
478
|
+
curl -X POST "http://localhost:3000/cache/foo?namespace=orders" \
|
479
|
+
-d "value=123&expires_in=60"
|
480
|
+
|
481
|
+
# Read from namespace
|
482
|
+
curl "http://localhost:3000/cache/foo?namespace=orders"
|
483
|
+
|
484
|
+
# Delete from namespace
|
485
|
+
curl -X DELETE "http://localhost:3000/cache/foo?namespace=orders"
|
486
|
+
|
487
|
+
```
|
488
|
+
|
489
|
+
---
|
490
|
+
|
491
|
+
## Project Philosophy
|
492
|
+
|
493
|
+
Mudis is intended to be a minimal, thread-safe, in-memory cache designed specifically for Ruby applications. It focuses on:
|
494
|
+
|
495
|
+
- In-process caching
|
496
|
+
- Fine-grained memory and namespace control
|
497
|
+
- Observability and testing friendliness
|
498
|
+
- Minimal external dependencies
|
499
|
+
- Configurability without complexity
|
500
|
+
|
501
|
+
The primary use cases are:
|
502
|
+
|
503
|
+
- Per-service application caches
|
504
|
+
- Short-lived local caching inside background jobs or API layers
|
505
|
+
|
506
|
+
Mudis is not intended to be a general-purpose, distributed caching platform. You are, however, welcome to build on top of Mudis if you want its functionality in such projects. E.g.,
|
507
|
+
|
508
|
+
- mudis-server – expose Mudis via HTTP, web sockets, hooks, etc
|
509
|
+
- mudis-broker – distributed key routing layer for coordinating multiple Mudis nodes
|
510
|
+
- mudis-activejob-store – adapter for using Mudis in job queues or retry buffers
|
511
|
+
|
512
|
+
---
|
513
|
+
|
357
514
|
## Roadmap
|
358
515
|
|
359
516
|
#### API Enhancements
|
@@ -379,14 +536,7 @@ MIT License © kiebor81
|
|
379
536
|
|
380
537
|
## Contributing
|
381
538
|
|
382
|
-
|
383
|
-
|
384
|
-
```bash
|
385
|
-
git clone https://github.com/kiebor81/mudis
|
386
|
-
cd mudis
|
387
|
-
bundle install
|
388
|
-
|
389
|
-
```
|
539
|
+
See [contributor's guide](CONTRIBUTING.md)
|
390
540
|
|
391
541
|
---
|
392
542
|
|
data/lib/mudis/version.rb
CHANGED
data/lib/mudis.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "json"
|
4
4
|
require "thread" # rubocop:disable Lint/RedundantRequireStatement
|
@@ -19,8 +19,8 @@ class Mudis # rubocop:disable Metrics/ClassLength
|
|
19
19
|
@stop_expiry = false # Signal for stopping expiry thread
|
20
20
|
|
21
21
|
class << self
|
22
|
-
attr_accessor :serializer, :compress, :
|
23
|
-
attr_reader :max_bytes
|
22
|
+
attr_accessor :serializer, :compress, :hard_memory_limit
|
23
|
+
attr_reader :max_bytes, :max_value_bytes
|
24
24
|
|
25
25
|
# Configures Mudis with a block, allowing customization of settings
|
26
26
|
def configure
|
@@ -35,6 +35,8 @@ class Mudis # rubocop:disable Metrics/ClassLength
|
|
35
35
|
|
36
36
|
# Applies the current configuration to Mudis
|
37
37
|
def apply_config!
|
38
|
+
validate_config!
|
39
|
+
|
38
40
|
self.serializer = config.serializer
|
39
41
|
self.compress = config.compress
|
40
42
|
self.max_value_bytes = config.max_value_bytes
|
@@ -42,6 +44,18 @@ class Mudis # rubocop:disable Metrics/ClassLength
|
|
42
44
|
self.max_bytes = config.max_bytes
|
43
45
|
end
|
44
46
|
|
47
|
+
# Validates the current configuration, raising errors for invalid settings
|
48
|
+
def validate_config! # rubocop:disable Metrics/AbcSize
|
49
|
+
if config.max_value_bytes && config.max_value_bytes > config.max_bytes
|
50
|
+
raise ArgumentError,
|
51
|
+
"max_value_bytes cannot exceed max_bytes"
|
52
|
+
end
|
53
|
+
|
54
|
+
raise ArgumentError, "max_value_bytes must be > 0" if config.max_value_bytes && config.max_value_bytes <= 0
|
55
|
+
|
56
|
+
raise ArgumentError, "buckets must be > 0" if config.buckets && config.buckets <= 0
|
57
|
+
end
|
58
|
+
|
45
59
|
# Returns a snapshot of metrics (thread-safe)
|
46
60
|
def metrics # rubocop:disable Metrics/MethodLength
|
47
61
|
@metrics_mutex.synchronize do
|
@@ -89,9 +103,18 @@ class Mudis # rubocop:disable Metrics/ClassLength
|
|
89
103
|
|
90
104
|
# Sets the maximum size for a single value in bytes
|
91
105
|
def max_bytes=(value)
|
106
|
+
raise ArgumentError, "max_bytes must be > 0" if value.to_i <= 0
|
107
|
+
|
92
108
|
@max_bytes = value
|
93
109
|
@threshold_bytes = (@max_bytes * 0.9).to_i
|
94
110
|
end
|
111
|
+
|
112
|
+
# Sets the maximum size for a single value in bytes, raising an error if invalid
|
113
|
+
def max_value_bytes=(value)
|
114
|
+
raise ArgumentError, "max_value_bytes must be > 0" if value && value.to_i <= 0
|
115
|
+
|
116
|
+
@max_value_bytes = value
|
117
|
+
end
|
95
118
|
end
|
96
119
|
|
97
120
|
# Node structure for the LRU doubly-linked list
|
@@ -107,7 +130,12 @@ class Mudis # rubocop:disable Metrics/ClassLength
|
|
107
130
|
|
108
131
|
# Number of cache buckets (shards). Default: 32
|
109
132
|
def self.buckets
|
110
|
-
@buckets
|
133
|
+
return @buckets if @buckets
|
134
|
+
|
135
|
+
val = config.buckets || ENV["MUDIS_BUCKETS"]&.to_i || 32
|
136
|
+
raise ArgumentError, "bucket count must be > 0" if val <= 0
|
137
|
+
|
138
|
+
@buckets = val
|
111
139
|
end
|
112
140
|
|
113
141
|
# --- Internal Structures ---
|
data/lib/mudis_config.rb
CHANGED
@@ -7,7 +7,8 @@ class MudisConfig
|
|
7
7
|
:compress,
|
8
8
|
:max_value_bytes,
|
9
9
|
:hard_memory_limit,
|
10
|
-
:max_bytes
|
10
|
+
:max_bytes,
|
11
|
+
:buckets
|
11
12
|
|
12
13
|
def initialize
|
13
14
|
@serializer = JSON # Default serialization strategy
|
@@ -15,5 +16,6 @@ class MudisConfig
|
|
15
16
|
@max_value_bytes = nil # Max size per value (optional)
|
16
17
|
@hard_memory_limit = false # Enforce max_bytes as hard cap
|
17
18
|
@max_bytes = 1_073_741_824 # 1 GB default max cache size
|
19
|
+
@buckets = nil # use nil to signal fallback to ENV or default
|
18
20
|
end
|
19
21
|
end
|
data/sig/mudis.rbs
CHANGED
@@ -3,14 +3,15 @@ class Mudis
|
|
3
3
|
class << self
|
4
4
|
attr_accessor serializer : Object
|
5
5
|
attr_accessor compress : bool
|
6
|
-
attr_accessor max_value_bytes : Integer?
|
7
6
|
attr_accessor hard_memory_limit : bool
|
8
7
|
attr_reader max_bytes : Integer
|
9
|
-
|
8
|
+
attr_reader max_value_bytes : Integer?
|
10
9
|
|
11
10
|
def configure: () { (config: MudisConfig) -> void } -> void
|
12
11
|
def config: () -> MudisConfig
|
13
12
|
def apply_config!: () -> void
|
13
|
+
|
14
|
+
def buckets: () -> Integer
|
14
15
|
end
|
15
16
|
|
16
17
|
# Lifecycle
|
data/sig/mudis_config.rbs
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "climate_control"
|
5
|
+
|
6
|
+
RSpec.describe "Mudis Configuration Guardrails" do # rubocop:disable Metrics/BlockLength
|
7
|
+
after { Mudis.reset! }
|
8
|
+
|
9
|
+
describe "bucket configuration" do
|
10
|
+
it "defaults to 32 buckets if ENV is nil" do
|
11
|
+
Mudis.instance_variable_set(:@buckets, nil) # force recomputation
|
12
|
+
ClimateControl.modify(MUDIS_BUCKETS: nil) do
|
13
|
+
expect(Mudis.send(:buckets)).to eq(32)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises if MUDIS_BUCKETS is 0 or less" do
|
18
|
+
expect do
|
19
|
+
Mudis.instance_variable_set(:@buckets, nil) # force recomputation
|
20
|
+
ClimateControl.modify(MUDIS_BUCKETS: "0") { Mudis.send(:buckets) }
|
21
|
+
end.to raise_error(ArgumentError, /bucket count must be > 0/)
|
22
|
+
|
23
|
+
expect do
|
24
|
+
Mudis.instance_variable_set(:@buckets, nil) # force recomputation
|
25
|
+
ClimateControl.modify(MUDIS_BUCKETS: "-5") { Mudis.send(:buckets) }
|
26
|
+
end.to raise_error(ArgumentError, /bucket count must be > 0/)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "memory configuration" do
|
31
|
+
it "raises if max_bytes is set to 0 or less" do
|
32
|
+
expect do
|
33
|
+
Mudis.max_bytes = 0
|
34
|
+
end.to raise_error(ArgumentError, /max_bytes must be > 0/)
|
35
|
+
|
36
|
+
expect do
|
37
|
+
Mudis.max_bytes = -1
|
38
|
+
end.to raise_error(ArgumentError, /max_bytes must be > 0/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "raises if max_value_bytes is 0 or less via config" do
|
42
|
+
expect do
|
43
|
+
Mudis.configure do |c|
|
44
|
+
c.max_value_bytes = 0
|
45
|
+
end
|
46
|
+
end.to raise_error(ArgumentError, /max_value_bytes must be > 0/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "raises if max_value_bytes exceeds max_bytes" do
|
50
|
+
expect do
|
51
|
+
Mudis.configure do |c|
|
52
|
+
c.max_bytes = 1_000_000
|
53
|
+
c.max_value_bytes = 2_000_000
|
54
|
+
end
|
55
|
+
end.to raise_error(ArgumentError, /max_value_bytes cannot exceed max_bytes/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mudis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kiebor81
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: climate_control
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.1.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.1.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rspec
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,8 +38,9 @@ dependencies:
|
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '3.12'
|
27
|
-
description:
|
28
|
-
|
41
|
+
description: Mudis is a fast, thread-safe, in-memory, sharded LRU cache for Ruby applications.
|
42
|
+
Inspired by Redis, it provides value serialization, optional compression, per-key
|
43
|
+
expiry, and metric tracking in a lightweight, dependency-free package.
|
29
44
|
email:
|
30
45
|
executables: []
|
31
46
|
extensions: []
|
@@ -39,6 +54,7 @@ files:
|
|
39
54
|
- lib/mudis_config.rb
|
40
55
|
- sig/mudis.rbs
|
41
56
|
- sig/mudis_config.rbs
|
57
|
+
- spec/guardrails_spec.rb
|
42
58
|
- spec/mudis_spec.rb
|
43
59
|
homepage: https://github.com/kiebor81/mudis
|
44
60
|
licenses:
|
@@ -62,6 +78,8 @@ requirements: []
|
|
62
78
|
rubygems_version: 3.5.17
|
63
79
|
signing_key:
|
64
80
|
specification_version: 4
|
65
|
-
summary: A fast in-memory Ruby LRU cache with compression
|
81
|
+
summary: A fast in-memory, thread-safe and high performance Ruby LRU cache with compression
|
82
|
+
and auto-expiry.
|
66
83
|
test_files:
|
84
|
+
- spec/guardrails_spec.rb
|
67
85
|
- spec/mudis_spec.rb
|