cds-caching 0.2.0 → 0.2.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.
- package/README.md +167 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,6 +93,97 @@ For more control, you can specify additional options:
|
|
|
93
93
|
}
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
+
### Real-World Usage and Deployment
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#### Storage Options
|
|
100
|
+
|
|
101
|
+
cds-caching provides two storage options:
|
|
102
|
+
|
|
103
|
+
##### In-Memory Cache (for small-scale use)
|
|
104
|
+
- Simple and fast, but not persistent
|
|
105
|
+
- Not suitable for production since Node.js runtime memory is limited
|
|
106
|
+
- Data is lost when the application restarts
|
|
107
|
+
|
|
108
|
+
##### Redis Cache (recommended for production)
|
|
109
|
+
- Persistent and supports distributed caching
|
|
110
|
+
- Works across multiple app instances, making it ideal for scalable applications
|
|
111
|
+
- Available on SAP BTP via hyperscaler options (e.g., AWS, Azure, Google Cloud)
|
|
112
|
+
- Even trial accounts provide Redis access
|
|
113
|
+
|
|
114
|
+
#### Development Setup
|
|
115
|
+
|
|
116
|
+
##### Running Redis Locally via Docker
|
|
117
|
+
For local development, Redis can be quickly set up using Docker. A simple docker-compose configuration provides a lightweight caching environment:
|
|
118
|
+
|
|
119
|
+
1. Create a `docker-compose.yml` file:
|
|
120
|
+
```yaml
|
|
121
|
+
services:
|
|
122
|
+
redis:
|
|
123
|
+
image: redis:latest
|
|
124
|
+
container_name: local-redis
|
|
125
|
+
ports:
|
|
126
|
+
- "6379:6379"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
2. Run Redis with:
|
|
130
|
+
```bash
|
|
131
|
+
docker compose up -d
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
3. Modify the `package.json` configuration to connect to the local Redis instance:
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"cds": {
|
|
138
|
+
"requires": {
|
|
139
|
+
"caching": {
|
|
140
|
+
"impl": "cds-caching",
|
|
141
|
+
"namespace": "myCache",
|
|
142
|
+
"store": "redis",
|
|
143
|
+
"[development]": {
|
|
144
|
+
"credentials": {
|
|
145
|
+
"host": "localhost",
|
|
146
|
+
"port": 6379
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Now, caching will be handled by Redis instead of in-memory storage during development.
|
|
156
|
+
|
|
157
|
+
#### Production Deployment on SAP BTP
|
|
158
|
+
|
|
159
|
+

|
|
160
|
+
|
|
161
|
+
For production deployments on SAP BTP, Redis can be provisioned as a managed service through the Redis on SAP BTP hyperscaler option. An instance can be provisioned via trial or even as a Free Tier to explore the service. However, for production scenarios the size of the Redis instance should match your caching requirements.
|
|
162
|
+
|
|
163
|
+
To bind Redis to your CAP application on SAP BTP, add the following configuration in `mta.yaml`. This will automatically create the service instance and bind your application to it. Since the credentials will automatically be fetched by CAP, make sure to maintain the service-tags to match the kind property of your cds-caching service(s) in the package.json:
|
|
164
|
+
|
|
165
|
+
```yaml
|
|
166
|
+
modules:
|
|
167
|
+
- name: cap-app-srv
|
|
168
|
+
# ... other module configuration ...
|
|
169
|
+
requires:
|
|
170
|
+
- name: redis-cache
|
|
171
|
+
|
|
172
|
+
resources:
|
|
173
|
+
- name: redis-cache
|
|
174
|
+
type: org.cloudfoundry.managed-service
|
|
175
|
+
parameters:
|
|
176
|
+
service: redis-cache
|
|
177
|
+
service-plan: trial
|
|
178
|
+
service-tags:
|
|
179
|
+
# Must match the kind property in the package.json
|
|
180
|
+
- cds-caching
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
> 👉 **Tip**: There is a detailed [blog series on Redis in SAP BTP](https://community.sap.com/t5/technology-blogs-by-sap/redis-on-sap-btp-understanding-service-entitlements-and-metrics/ba-p/13738371) explaining how to set up Redis and connect via SSH for local/hybrid testing, as this is by default not possible.
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
96
187
|
### Usage Patterns
|
|
97
188
|
|
|
98
189
|
The caching service provides a flexible API for caching data in CAP applications. Here are the key usage patterns:
|
|
@@ -266,7 +357,49 @@ const result = await cache.exec("key", async () => {
|
|
|
266
357
|
})
|
|
267
358
|
```
|
|
268
359
|
|
|
269
|
-
#### 2.
|
|
360
|
+
#### 2. Key-Based
|
|
361
|
+
|
|
362
|
+
Key-based invalidation is a way to invalidate cache entries based on a specific key.
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
await cache.delete("key")
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Keys are critical for cache invalidation. To allow custom key management, you can override the auto-generated key. This option is available for all essential methods (e.g cache.set, cache.run, cache.send, cache.createKey) and for the annotations.
|
|
369
|
+
|
|
370
|
+
```javascript
|
|
371
|
+
// No key override given, string will just be used as keys
|
|
372
|
+
await cache.set('key', 'value') // key: key
|
|
373
|
+
|
|
374
|
+
// No key override given, objects will be smartly hashed
|
|
375
|
+
await cache.set(SELECT.from(Foo)) // key: bd3f3690d3e96a569bd89d9e207a89af
|
|
376
|
+
|
|
377
|
+
// Automatically build the key for retrieval/deletion
|
|
378
|
+
cache.createKey(SELECT.from(Foo)) // key: bd3f3690d3e96a569bd89d9e207a89af
|
|
379
|
+
|
|
380
|
+
// Override and use your own key based on a fixed value
|
|
381
|
+
await cache.set(SELECT.from(Foo, 1), { key: { value: "foo:1" } })
|
|
382
|
+
|
|
383
|
+
// Override and only for requests, use request context information
|
|
384
|
+
await cache.run(req, remoteService, { key: { template: "mykey:{tenant}:{user}:{locale}:{hash}" } })
|
|
385
|
+
|
|
386
|
+
// This requests will be cached for all users and for each locale
|
|
387
|
+
await cache.set(req, remoteService, { key: { template: "mykey:{user}:{locale}:{hash}" } })
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Overriding keys support the following configuration options:
|
|
391
|
+
- `value` – generates a static value
|
|
392
|
+
- `prefix` – will add this piece at the beginning
|
|
393
|
+
- `suffix` - will ad this piece at the end
|
|
394
|
+
- `template` - will set a value filled with placeholders, available placeholders are (only relevant for cds.Requests):
|
|
395
|
+
- `{user}`: The current user
|
|
396
|
+
- `{tenant}`: The current tenant
|
|
397
|
+
- `{locale}`: The current locale
|
|
398
|
+
- `{hash}`: The hash of the request query/params/data/path/etc.
|
|
399
|
+
|
|
400
|
+
With well-structured keys, invalidating cache entries becomes a lot easier. However, for more complex scenarios tags provide an even more effective solution, as tags can automatically be created based on the cached data.
|
|
401
|
+
|
|
402
|
+
#### 3. Tag-Based
|
|
270
403
|
|
|
271
404
|
Tags are a way to invalidate cache entries based on a specific tag. Tags need to be provided explicitly when storing a value in the cache and are supported for all cache methods (e.g. `set`, `run`, `send`, `wrap`, `exec`).
|
|
272
405
|
Tags can be provided as an array of strings or as an array of objects with the following properties:
|
|
@@ -434,7 +567,8 @@ The following properties are accepted:
|
|
|
434
567
|
| Property | Description | Example |
|
|
435
568
|
| ------------- | ------------- | ----------
|
|
436
569
|
| ttl | Time-to-live in milliseconds. | `1000`
|
|
437
|
-
|
|
|
570
|
+
| key | Key override for the cache for full control over the key management (see chapter Cache Invalidation Strategies) | `{template: 'user-{user}', value: '123'}`
|
|
571
|
+
| tags | Array of tags to associate with the value. Tags can be dynamic based on the stored cache data (see chapter Cache Invalidation Strategies) | `[{template: 'user-{user}', value: '123'}]`
|
|
438
572
|
|
|
439
573
|
---
|
|
440
574
|
|
|
@@ -572,7 +706,7 @@ The result of the function.
|
|
|
572
706
|
|
|
573
707
|
---
|
|
574
708
|
|
|
575
|
-
### `await cache.iterator()
|
|
709
|
+
### `await cache.iterator() : AsyncIterator<{ key: string, value: { value: any, tags: string[], timestamp: number } }>`
|
|
576
710
|
|
|
577
711
|
Returns an iterator over all cache entries.
|
|
578
712
|
|
|
@@ -582,6 +716,36 @@ An iterator over all cache entries.
|
|
|
582
716
|
|
|
583
717
|
---
|
|
584
718
|
|
|
719
|
+
### `await cache.tags(key: any) : string[]`
|
|
720
|
+
|
|
721
|
+
Returns the tags for a given key.
|
|
722
|
+
|
|
723
|
+
#### `key: any`
|
|
724
|
+
|
|
725
|
+
The key to get the tags for. The key handling is the same as for the `createKey` method.
|
|
726
|
+
|
|
727
|
+
#### Returns
|
|
728
|
+
|
|
729
|
+
An array of tags. If the key does not exist, an empty array is returned.
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
### `await cache.metadata(key: any) : { tags: string[], timestamp: number } | undefined`
|
|
734
|
+
|
|
735
|
+
Returns the metadata for a given key.
|
|
736
|
+
|
|
737
|
+
#### `key: any`
|
|
738
|
+
|
|
739
|
+
The key to get the metadata for. The key handling is the same as for the `createKey` method.
|
|
740
|
+
|
|
741
|
+
#### Returns
|
|
742
|
+
|
|
743
|
+
An object containing the metadata for the given key or `undefined` if the key does not exist. The metadata object contains the following properties:
|
|
744
|
+
|
|
745
|
+
- `tags`: An array of tags.
|
|
746
|
+
- `timestamp`: The timestamp of the cache entry.
|
|
747
|
+
|
|
748
|
+
---
|
|
585
749
|
|
|
586
750
|
### Contributing
|
|
587
751
|
|