@andrash/prisma-cache
v1.3.0
Published
This is a tool that caches data from prisma. Note that this cache does not implement any cache invalidation mechanism, so it is only suitable for low data volume where **all data** should be cached.
Downloads
10
Readme
Welcome to Prisma Cache (by Andrash)
[English] This package is a simple key-value store that stores data in both memory and any Prisma-compatible database.
[Traditional Chinese (Taiwan)] 本專案旨在提供一個簡單的「鍵->值」快取容器。它將資料存儲在記憶體中,並且同時將一個副本儲存在(任何與 Prisma 相容的) 資料庫中。這樣,當伺服器重新啟動時,即可從資料庫中將資料還原回到快取容器中。
Note that there is no built-in cache invalidation or free-up mechanism since the purpose of this tool is to create a simple key-value store that keeps all data (smaller scale) in memory and pushs a copy in a database so it can be restored when the server is restarted.
請特別注意,這個工具並不提供快取失效或釋放機制。因為這個工具的主要用途在於建立一個簡單的「鍵->值」快取容器,並將較小規模的資料 全部 存儲在記憶體中,同時保存一份副本在資料庫中,以便在伺服器重新啟動時將資料還原至快取容器中。
It also uses the type definitions that come from the Prisma Client to ensure that the data stored in the cache is consistent with the Prisma model.
此外,它運用了來自 Prisma Client 的 TypeScript 型別定義,以確保儲存在快取中的資料與由 Prisma 模型所定義的一致。
Installation 安裝說明
npm i @andrash/prisma-cache
Please ensure that Prisma ORM is installed and Prisma client is generated.
使用前請先安裝 Prisma ORM 並且生成 Prisma client。
npm i @prisma/client
npx prisma generate
Usage 使用方法
import { PrismaCache } from "@andrash/prisma-cache";
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
// Provide the user model and the primary key field name
const userCache = new PrismaCache(prisma, prisma.user, "user", "userId");
async function main() {
// Always connect to the database before initializing the cache
await prisma.$connect();
// Always call the `init` method before using the cache
// Otherwise, bad things will happen ;)
userCache.init();
// Pull data from the database and store it in the cache,
// it will also return a copy of the data
let { created } = await userCache.pull();
console.log(created);
//[{userId: 1, name: 'Alice', age: 20}, {userId: 2, name: 'Bob', age: 30}]
// Update data in both cache and database
let data = await userCache.update(1, { name: "Alice Smith" });
console.log(data); //{userId: 1, name: 'Alice Smith', age: 20}
// Get data from cache without querying the database
data = userCache.get(2);
console.log(data); //{userId: 2, name: 'Bob', age: 30}
// Patch data in cache **without updating the database**
// This is considered an unsafe operation but useful in some cases
data = userCache.patch(2, { age: 31 });
console.log(data); //{userId: 2, name: 'Bob', age: 31}
// PrismaCache will mark the data as unsynced when you perform an
// unsafe operation that changes the data in the cache but not in the database.
console.log(userCache.getIsSynced(2)); //false
// And you can bring the data back to sync by calling the `push` method.
// This will update the database with the data in the cache.
await userCache.push();
// Alternatively, you can discard the changes in the cache and reload all unsynced data from the database. This will also bring the data back to sync.
await userCache.pull();
}
main();
CRUD Operations 增/刪/改/查操作
There are two sets of CRUD (Create, Read, Update, Delete) operations: safe and unsafe.
本套件包含兩組 CRUD (增、刪、改、查) 操作,分為「安全操作」與「不安全操作」。
Safe Operations: 安全操作
All safe operations are async methods
that will update the data in both the cache and the database:
不會導致快取與資料庫之間的資料失去同步。適合較單純的使用情境:
- async create() --> C
- async pull() --> R
- async push() --> U
- async update() --> U
- async delete() --> D
- async truncate() --> D
All data that has been changed by safe operations (except Read operations) will be marked as synced
and will not be processed (by default) when calling the push()
or pull()
method.
使用安全操作後,資料將被標記為「已同步」,並在呼叫 push()
或 pull()
方法時,(在預設情況下)這些資料將不會被處理。
Unsafe Operations 不安全操作
All unsafe operations are synchronous methods
that will only update the data in the cache:
可能導致快取與資料庫之間的資料失去同步,但在某些情況下必要且有用:
- set() --> C
- get() --> R
- getMany() --> R
- patch() --> U
- unset() --> D
- clear() --> D
All data that has been changed by unsafe operations (except Read operations) will be marked as unsynced
and will be processed (by default) when calling the push()
or pull()
method.
使用不安全操作後,資料將被標記為「未同步」,並且在呼叫 push()
或 pull()
方法時,(在預設情況下)這些資料將會被處理,以便使其回到同步狀態。
Handling Sync Status 處理資料同步狀態
Usually, we do not need to worry about the sync status of the data, as the package will automatically manage it for you.
However, in some advanced cases, you may need to check or even manually manage the sync status of the data.
在一般情況下,我們不需要擔心資料的同步狀態,因為本套件將自動為您管理。但在某些進階情況下,您可能需要檢查甚至手動管理資料的同步狀態。
To check the sync status of the data:
查看資料的同步狀態:
// Check if the data is synced with the database
console.log(userCache.getIsSynced(1)); //true
Since the sync status tracking mechanism can only track the changes made through this package. If you make changes to the database directly with Prisma, the sync status will not be updated and you may need to manually manage the sync status.
同步狀態追蹤機制僅能追蹤透過本套件所做的更改。如果您直接使用 Prisma 更新資料庫,同步狀態將不會被更新,您可能需要手動管理同步狀態。
for example, if you update the data directly with Prisma:
在更新資料庫後,使用pull()
方法將資料從資料庫拉回快取中,以恢復同步狀態:
await prisma.user.update({
where: { userId: 1 },
data: { name: "Alice" },
});
// Manually pull the data from the database to bring it back to sync
await userCache.pull(1);
Or you can do this instead to avoid the extra query made by pull
:
如果要避免 pull
方法造成的額外資料庫查詢,可以使用以下方法:
const data = await prisma.user.update({
where: { userId: 1 },
data: { name: "Alice" },
});
// Manually update the cache with the new data
userCache.set(data); // This will mark the data as unsynced
userCache.setIsSynced(1); // So you need to mark it as synced manually
Alternatively, you can also mark the data as unsynced and perform a push()
or pull()
operation later to bring it back to sync.
另一種方法是將資料標記為「未同步」,並稍後執行 push()
或 pull()
操作以將其恢復為同步狀態。
await prisma.user.update({
where: { userId: 1 },
data: { name: "Alice Z." },
});
// Manually mark the data as unsynced so it can be handled later
userCache.setIsUnsynced(1);
// Do some other changes...
await prisma.user.update({
where: { userId: 2 },
data: { name: "Bob Jr." },
});
userCache.setIsUnsynced(2);
// And then push or pull the data to bring it back to sync at once
await userCache.pull();
Note that you don't have to call push()
manually, if you already enabled the auto-push feature.
如果您已經啟用了自動推送 (auto-push) 功能,則無需手動呼叫 push()
。
Auto Push 自動推送變更
This feature will collect all the changes (unsynced data caused by unsafe operations) in a certain period of time (5 seconds for the example below) and push them to the database in one batch. This is useful when you have a lot of changes in a short period of time and you want to push them in one batch to reduce the number of database queries.
此功能將在一段時間內 (以下範例為 5 秒) 收集所有變更 (即由不安全操作導致的未同步資料),並將它們一次性推送到資料庫中。當您在短時間內有大量變更,並且希望將它們一次性推送以減少資料庫查詢次數時,這是非常有用的。
// To enable the auto push feature, you can set the `autoSaveDelayMs` parameter in the constructor.
const autoSaveDelayMs = 5000; // 5 seconds
const userCache = new PrismaCache(
prisma,
prisma.user,
"user",
"userId",
autoSaveDelayMs
);
// Or you can set it later
userCache.autoSaveDelayMs = 5000;
// You can also disable it by setting it to 0
userCache.autoSaveDelayMs = 0;
Iterating through the cache 遍歷所有快取資料
To iterate through all the data in the cache, you can do the following:
以下是遍歷快取中所有資料的兩種方法:
// With `userCache.forEach()` method
userCache.forEach((data, id, cache) => {
console.log(data, id);
});
// With `userCache.ids` property
for (const id of userCache.ids) {
const data = userCache.get(id);
console.log(data, id);
}