@gravito/stasis 3.0.1 → 3.1.0

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.
package/README.md CHANGED
@@ -1,13 +1,18 @@
1
- # @gravito/stasis
1
+ # @gravito/stasis 🧊
2
2
 
3
- > The Standard Cache Orbit for Galaxy Architecture.
3
+ > High-performance caching and rate-limiting Orbit for Gravito.
4
4
 
5
- Provides a Laravel-like cache layer with:
5
+ `@gravito/stasis` provides a robust, developer-friendly caching layer for the Gravito framework. Inspired by Laravel's cache system, it offers a unified API for multiple storage backends, distributed locking, and integrated rate limiting.
6
6
 
7
- - `CacheManager` + `CacheRepository` API (`get/put/add/remember/forever/increment/decrement/pull`)
8
- - Multiple stores (`memory`, `file`, `null`, `custom`)
9
- - Tags (memory store) and Locks (`lock().block()`)
10
- - Hook events (`cache:hit`, `cache:miss`, `cache:write`, `cache:forget`, `cache:flush`, `cache:init`)
7
+ ## 🌟 Key Features
8
+
9
+ - **🚀 Unified Cache API**: Simple `get`, `put`, `remember`, and `forever` methods across all drivers.
10
+ - **💾 Multiple Storage Drivers**: Native support for Memory, Redis, File-based, and Null storage.
11
+ - **🔒 Distributed Locks**: Prevent race conditions with atomic, cross-process locks.
12
+ - **⚡ Flexible Caching (SWR)**: Stale-While-Revalidate support to serve data fast while refreshing in the background.
13
+ - **🚦 Integrated Rate Limiting**: Throttling mechanism built directly on top of your cache infrastructure.
14
+ - **🏷️ Cache Tagging**: Group related items for bulk invalidation (supported in Memory driver).
15
+ - **🪝 Hook System**: Lifecycle events for monitoring cache hits, misses, and writes.
11
16
 
12
17
  ## 📦 Installation
13
18
 
@@ -15,72 +20,96 @@ Provides a Laravel-like cache layer with:
15
20
  bun add @gravito/stasis
16
21
  ```
17
22
 
18
- ## 🚀 Usage
23
+ ## 🚀 Quick Start
24
+
25
+ ### 1. Register the Orbit
19
26
 
20
27
  ```typescript
21
- import { PlanetCore } from '@gravito/core';
22
- import orbitCache from '@gravito/stasis';
23
-
24
- const core = new PlanetCore();
25
-
26
- // Initialize Cache Orbit (Laravel-like config)
27
- const cache = orbitCache(core, {
28
- exposeAs: 'cache',
29
- default: 'memory',
30
- prefix: 'app_cache:',
31
- defaultTtl: 60, // seconds
32
- // Low-overhead hook dispatch (default: 'async')
33
- // Use 'sync' + throwOnEventError for development/debug.
34
- eventsMode: 'async',
35
- stores: {
36
- memory: { driver: 'memory', maxItems: 10_000 },
37
- file: { driver: 'file', directory: './tmp/cache' },
38
- null: { driver: 'null' },
28
+ import { PlanetCore, defineConfig } from '@gravito/core'
29
+ import { OrbitStasis } from '@gravito/stasis'
30
+
31
+ const config = defineConfig({
32
+ config: {
33
+ cache: {
34
+ default: 'memory',
35
+ stores: {
36
+ memory: { driver: 'memory', maxItems: 5000 },
37
+ redis: { driver: 'redis', connection: 'default' }
38
+ }
39
+ }
39
40
  },
40
- });
41
-
42
- // Use in routes
43
- core.app.get('/heavy-data', async (c) => {
44
- // Either use the manager returned from orbitCache(...) or request-scoped access:
45
- // const cache = c.get('cache');
46
-
47
- const data = await cache.remember('heavy_key', 300, async () => {
48
- // Expensive computation...
49
- return { result: 42 };
50
- });
51
-
52
- return c.json(data);
53
- });
41
+ orbits: [new OrbitStasis()]
42
+ })
43
+
44
+ const core = await PlanetCore.boot(config)
54
45
  ```
55
46
 
56
- ### Tags (memory store)
47
+ ### 2. Basic Caching
48
+
49
+ ```typescript
50
+ const cache = core.container.make('cache')
57
51
 
58
- ```ts
59
- const cache = c.get('cache');
60
- await cache.tags(['users']).set('user:1', { id: 1 }, 60);
61
- await cache.tags(['users']).clear(); // flush only tagged keys
52
+ // Simple storage
53
+ await cache.put('stats:total', 100, 3600) // Store for 1 hour
54
+
55
+ // "Remember" pattern (Get or Set)
56
+ const users = await cache.remember('users:all', 300, async () => {
57
+ return await db.users.findMany()
58
+ })
62
59
  ```
63
60
 
64
- ### Locks
61
+ ### 3. Distributed Locking
65
62
 
66
- ```ts
67
- const cache = c.get('cache');
68
- await cache.lock('jobs:rebuild', 10).block(5, async () => {
69
- // exclusive section
70
- });
63
+ ```typescript
64
+ const lock = cache.lock('process-invoice:123', 10)
65
+
66
+ if (await lock.get()) {
67
+ try {
68
+ // Perform critical task...
69
+ } finally {
70
+ await lock.release()
71
+ }
72
+ }
71
73
  ```
72
74
 
73
- ## 🪝 Hooks
75
+ ## 🚦 Rate Limiting
74
76
 
75
- - `cache:miss` - Fired when data is not found in cache.
76
- - `cache:hit` - Fired when data is retrieved from cache.
77
- - `cache:write` - Fired when writing cache.
78
- - `cache:forget` - Fired when forgetting cache.
79
- - `cache:flush` - Fired when flushing cache.
80
- - `cache:init` - Fired when the orbit is installed.
77
+ Easily throttle requests or actions using your cache backend.
78
+
79
+ ```typescript
80
+ const limiter = cache.limiter()
81
81
 
82
- By default, hook events run in `async` mode and never block cache reads/writes. For debug, set:
82
+ if (await limiter.tooManyAttempts('login:127.0.0.1', 5)) {
83
+ const seconds = await limiter.availableIn('login:127.0.0.1')
84
+ throw new Error(`Too many attempts. Try again in ${seconds}s.`)
85
+ }
83
86
 
84
- ```ts
85
- orbitCache(core, { eventsMode: 'sync', throwOnEventError: true });
87
+ await limiter.hit('login:127.0.0.1', 60) // Decay in 60s
86
88
  ```
89
+
90
+ ## 🛠️ Supported Drivers
91
+
92
+ | Driver | Best For | Features |
93
+ |---|---|---|
94
+ | **Memory** | Local dev & Small apps | Fast, Tags, LRU |
95
+ | **Redis** | Distributed production | Multi-node, Locks, Persistent |
96
+ | **File** | Simple persistence | No external deps |
97
+ | **Null** | Testing / Disabling cache | No-op |
98
+
99
+ ## 🧩 API Reference
100
+
101
+ ### `CacheManager`
102
+ - `cache.get(key, default?)`: Retrieve an item.
103
+ - `cache.put(key, value, ttl?)`: Store an item.
104
+ - `cache.remember(key, ttl, callback)`: Get or execute callback and store.
105
+ - `cache.flexible(key, ttl, stale, callback)`: Stale-While-Revalidate.
106
+ - `cache.increment / decrement`: Atomic numeric updates.
107
+ - `cache.tags(['tag1']).flush()`: Invalidate by tag.
108
+
109
+ ## 🤝 Contributing
110
+
111
+ We welcome contributions! Please see our [Contributing Guide](../../CONTRIBUTING.md) for details.
112
+
113
+ ## 📄 License
114
+
115
+ MIT © Carl Lee
package/README.zh-TW.md CHANGED
@@ -1,38 +1,115 @@
1
- # @gravito/stasis
1
+ # @gravito/stasis 🧊
2
2
 
3
- > Gravito 的快取 Orbit,提供類 Laravel 的 Cache API。
3
+ > 高效能快取與速率限制 (Rate Limiting) Orbit,專為 Gravito 設計。
4
4
 
5
- ## 安裝
5
+ `@gravito/stasis` 為 Gravito 框架提供了一個強大且開發者友善的快取層。受 Laravel 快取系統啟發,它為多種存儲後端、分佈式鎖定以及整合式速率限制提供了統一的 API。
6
+
7
+ ## 🌟 核心特性
8
+
9
+ - **🚀 統一快取 API**:在所有驅動程式中提供簡潔的 `get`、`put`、`remember` 與 `forever` 方法。
10
+ - **💾 多種存儲驅動**:原生支援 Memory、Redis、檔案 (File) 以及 Null 存儲。
11
+ - **🔒 分佈式鎖 (Distributed Locks)**:透過原子性的跨進程鎖定防止競態條件 (Race Conditions)。
12
+ - **⚡ 彈性快取 (SWR)**:支援 Stale-While-Revalidate 模式,在背景更新數據的同時快速響應請求。
13
+ - **🚦 整合式速率限制**:直接在快取基礎設施上構建的流量節流機制。
14
+ - **🏷️ 快取標籤 (Tagging)**:支援將相關項目分組,以便進行批量刪除(Memory 驅動支援)。
15
+ - **🪝 Hook 系統**:提供生命週期事件,用於監控快取命中 (Hit)、未命中 (Miss) 與寫入。
16
+
17
+ ## 📦 安裝
6
18
 
7
19
  ```bash
8
20
  bun add @gravito/stasis
9
21
  ```
10
22
 
11
- ## 快速開始
23
+ ## 🚀 快速上手
24
+
25
+ ### 1. 註冊 Orbit
12
26
 
13
27
  ```typescript
14
- import { PlanetCore } from '@gravito/core'
15
- import orbitCache from '@gravito/stasis'
16
-
17
- const core = new PlanetCore()
18
-
19
- const cache = orbitCache(core, {
20
- exposeAs: 'cache',
21
- default: 'memory',
22
- prefix: 'app_cache:',
23
- defaultTtl: 60,
24
- stores: {
25
- memory: { driver: 'memory', maxItems: 10_000 },
26
- file: { driver: 'file', directory: './tmp/cache' },
27
- null: { driver: 'null' },
28
+ import { PlanetCore, defineConfig } from '@gravito/core'
29
+ import { OrbitStasis } from '@gravito/stasis'
30
+
31
+ const config = defineConfig({
32
+ config: {
33
+ cache: {
34
+ default: 'memory',
35
+ stores: {
36
+ memory: { driver: 'memory', maxItems: 5000 },
37
+ redis: { driver: 'redis', connection: 'default' }
38
+ }
39
+ }
28
40
  },
41
+ orbits: [new OrbitStasis()]
29
42
  })
30
43
 
31
- core.app.get('/heavy-data', async (c) => {
32
- const data = await cache.remember('heavy_key', 300, async () => {
33
- return { result: 42 }
34
- })
44
+ const core = await PlanetCore.boot(config)
45
+ ```
46
+
47
+ ### 2. 基礎快取操作
35
48
 
36
- return c.json(data)
49
+ ```typescript
50
+ const cache = core.container.make('cache')
51
+
52
+ // 簡單存儲
53
+ await cache.put('stats:total', 100, 3600) // 存儲 1 小時
54
+
55
+ // "Remember" 模式 (讀取或設置)
56
+ const users = await cache.remember('users:all', 300, async () => {
57
+ return await db.users.findMany()
37
58
  })
38
59
  ```
60
+
61
+ ### 3. 分佈式鎖定
62
+
63
+ ```typescript
64
+ const lock = cache.lock('process-invoice:123', 10)
65
+
66
+ if (await lock.get()) {
67
+ try {
68
+ // 執行關鍵任務...
69
+ } finally {
70
+ await lock.release()
71
+ }
72
+ }
73
+ ```
74
+
75
+ ## 🚦 速率限制 (Rate Limiting)
76
+
77
+ 輕鬆地使用您的快取後端來限制請求或操作的頻率。
78
+
79
+ ```typescript
80
+ const limiter = cache.limiter()
81
+
82
+ if (await limiter.tooManyAttempts('login:127.0.0.1', 5)) {
83
+ const seconds = await limiter.availableIn('login:127.0.0.1')
84
+ throw new Error(`嘗試次數過多。請在 ${seconds} 秒後重試。`)
85
+ }
86
+
87
+ await limiter.hit('login:127.0.0.1', 60) // 60 秒後衰減
88
+ ```
89
+
90
+ ## 🛠️ 支援的驅動程式 (Drivers)
91
+
92
+ | 驅動名稱 | 適用場景 | 核心功能 |
93
+ |---|---|---|
94
+ | **Memory** | 本地開發與小型應用 | 極速、標籤支援、LRU |
95
+ | **Redis** | 分佈式生產環境 | 多節點共享、鎖定、持久化 |
96
+ | **File** | 簡單的持久化需求 | 無外部依賴 |
97
+ | **Null** | 測試或停用快取 | 不執行任何操作 |
98
+
99
+ ## 🧩 API 參考
100
+
101
+ ### `CacheManager`
102
+ - `cache.get(key, default?)`:讀取項目。
103
+ - `cache.put(key, value, ttl?)`:存儲項目。
104
+ - `cache.remember(key, ttl, callback)`:讀取或執行回調並存儲。
105
+ - `cache.flexible(key, ttl, stale, callback)`:Stale-While-Revalidate 模式。
106
+ - `cache.increment / decrement`:原子性的數值更新。
107
+ - `cache.tags(['tag1']).flush()`:按標籤清除快取。
108
+
109
+ ## 🤝 參與貢獻
110
+
111
+ 我們歡迎任何形式的貢獻!詳細資訊請參閱 [貢獻指南](../../CONTRIBUTING.md)。
112
+
113
+ ## 📄 開源授權
114
+
115
+ MIT © Carl Lee