mudis 0.4.3 → 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 +174 -25
- data/lib/mudis/version.rb +1 -1
- metadata +6 -4
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,11 +305,10 @@ 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`|
|
312
|
-
| `buckets` | Number of memory buckets (shards) | `32` |
|
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`|
|
313
312
|
|
314
313
|
Buckets can also be set using a `MUDIS_BUCKETS` environment variable.
|
315
314
|
|
@@ -321,21 +320,69 @@ When setting `serializer`, be mindful of the below
|
|
321
320
|
| `JSON` | Cross-language interoperability |
|
322
321
|
| `Oj` | API-heavy apps using JSON at scale |
|
323
322
|
|
324
|
-
|
323
|
+
---
|
324
|
+
|
325
|
+
## Benchmarks
|
326
|
+
|
327
|
+
#### Serializer(s)
|
325
328
|
|
326
|
-
|
329
|
+
_100000 iterations_
|
327
330
|
|
328
|
-
| Serializer |
|
329
|
-
|
330
|
-
| oj |
|
331
|
-
| marshal |
|
332
|
-
| json |
|
333
|
-
| oj + zlib |
|
334
|
-
| marshal + zlib |
|
335
|
-
| 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 |
|
336
339
|
|
337
340
|
> If opting for OJ, you will need to install the dependency in your project and configure as needed.
|
338
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
|
+
|
339
386
|
---
|
340
387
|
|
341
388
|
## Graceful Shutdown
|
@@ -355,6 +402,115 @@ at_exit { Mudis.stop_expiry_thread }
|
|
355
402
|
|
356
403
|
---
|
357
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
|
+
|
358
514
|
## Roadmap
|
359
515
|
|
360
516
|
#### API Enhancements
|
@@ -380,14 +536,7 @@ MIT License © kiebor81
|
|
380
536
|
|
381
537
|
## Contributing
|
382
538
|
|
383
|
-
|
384
|
-
|
385
|
-
```bash
|
386
|
-
git clone https://github.com/kiebor81/mudis
|
387
|
-
cd mudis
|
388
|
-
bundle install
|
389
|
-
|
390
|
-
```
|
539
|
+
See [contributor's guide](CONTRIBUTING.md)
|
391
540
|
|
392
541
|
---
|
393
542
|
|
data/lib/mudis/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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
|
@@ -38,8 +38,9 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.12'
|
41
|
-
description:
|
42
|
-
|
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.
|
43
44
|
email:
|
44
45
|
executables: []
|
45
46
|
extensions: []
|
@@ -77,7 +78,8 @@ requirements: []
|
|
77
78
|
rubygems_version: 3.5.17
|
78
79
|
signing_key:
|
79
80
|
specification_version: 4
|
80
|
-
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.
|
81
83
|
test_files:
|
82
84
|
- spec/guardrails_spec.rb
|
83
85
|
- spec/mudis_spec.rb
|