Cache
Core ships with a cache abstraction that makes it easy to switch from an in-memory cache to a redis-based one. The default driver that is shipped provides an in-memory cache but using your own cache driver is just as easy.
Cache Usage
Create an instance
1import { Contracts } from "@mainsail/contracts";2 3const cacheStore = app.get<Contracts.Kernel.CacheStore<string, string>>(Identifiers.Services.Cache.Factory)()
Get all of the items in the cache
1cacheStore.all();
Get the keys of the cache items
1cacheStore.keys();
Get the values of the cache items
1cacheStore.values();
Retrieve an item from the cache by key
1cacheStore.get("key");
Retrieve multiple items from the cache by key
1cacheStore.getMany(["key1", "key2"]);
Store an item in the cache for a given number of seconds
1cacheStore.put("key", "value", 60);
Store multiple items in the cache for a given number of seconds
1cacheStore.putMany(["value1", "value2"], 60);
Determine if an item exists in the cache
1cacheStore.has("key");
Determine multiple items exist in the cache
1cacheStore.hasMany(["key1", "key2"]);
Determine if an item doesn’t exist in the cache
1cacheStore.missing("key");
Determine multiple items don’t exist in the cache
1cacheStore.missingMany(["key1", "key2"]);
Store an item in the cache indefinitely
1cacheStore.forever("key", "value");
Store multiple items in the cache indefinitely
1cacheStore.foreverMany(["value1", "value2"]);
Remove an item from the cache
1cacheStore.forget("key");
Remove multiple items from the cache
1cacheStore.forgetMany(["key1", "key2"]);
Remove all items from the cache
1cacheStore.flush();
Extending
As explained in a previous article, it is possible to extend Core services due to the fact that a Manager pattern is used. Lets go over a quick example of how you could implement your own cache store.
Implementing the Driver
Implementing a new driver is as simple as importing the cache store contract that needs to be satisfied and implement the methods specified in it.
1import { Contracts } from "@mainsail/contracts"; 2 3export class MemoryCacheStore<K, T> implements Contracts.Kernel.CacheStore<K, T> { 4 private readonly store: Map<K, T> = new Map<K, T>(); 5 6 public async make(): Promise<Contracts.Kernel.CacheStore<K, T>> { 7 return this; 8 } 9 10 public async all(): Promise<Array<[K, T]>> {11 return Array.from(this.store.entries());12 }13 14 public async keys(): Promise<K[]> {15 return Array.from(this.store.keys());16 }17 18 public async values(): Promise<T[]> {19 return Array.from(this.store.values());20 }21 22 public async get(key: K): Promise<T | undefined> {23 return this.store.get(key);24 }25 26 public async getMany(keys: K[]): Promise<Array<T | undefined>> {27 return keys.map((key: K) => this.store.get(key));28 }29 30 public async put(key: K, value: T, seconds?: number): Promise<boolean> {31 this.store.set(key, value);32 33 return this.has(key);34 }35 36 public async putMany(values: Array<[K, T]>, seconds?: number): Promise<boolean[]> {37 return Promise.all(values.map(async (value: [K, T]) => this.put(value[0], value[1])));38 }39 40 public async has(key: K): Promise<boolean> {41 return this.store.has(key);42 }43 44 public async hasMany(keys: K[]): Promise<boolean[]> {45 return Promise.all(keys.map(async (key: K) => this.has(key)));46 }47 48 public async missing(key: K): Promise<boolean> {49 return !this.store.has(key);50 }51 52 public async missingMany(keys: K[]): Promise<boolean[]> {53 return Promise.all([...keys].map(async (key: K) => this.missing(key)));54 }55 56 public async forever(key: K, value: T): Promise<boolean> {57 // This in-memory store doesn't offer any persistence.58 }59 60 public async foreverMany(values: Array<[K, T]>): Promise<boolean[]> {61 // This in-memory store doesn't offer any persistence.62 }63 64 public async forget(key: K): Promise<boolean> {65 this.store.delete(key);66 67 return this.missing(key);68 }69 70 public async forgetMany(keys: K[]): Promise<boolean[]> {71 return Promise.all(keys.map(async (key: K) => this.forget(key)));72 }73 74 public async flush(): Promise<boolean> {75 this.store.clear();76 77 return this.store.size === 0;78 }79 80 public async getPrefix(): Promise<string> {81 // This in-memory store doesn't offer any persistence.82 }83}
Implementing the service provider
Now that we have implemented our memory driver for the cache service, we can create a service provider to register it.
1import { Providers, Services } from "@mainsail/kernel"; 2import { Contracts } from "@mainsail/contracts"; 3 4export class ServiceProvider extends Providers.ServiceProvider { 5 public async register(): Promise<void> { 6 const cacheManager: Services.Cache.CacheManager = this.app.get<Services.Cache.CacheManager>( 7 Identifiers.Services.Cache.Manager, 8 ); 9 10 await cacheManager.extend("memory", MemoryCacheStore);11 }12}
- We retrieve an instance of the cache manager that is responsible for managing cache drivers.
- We call the
extend
method with an asynchronous function which is responsible for creating the cache store instance.
Last updated 9 months ago
Edit Page