Pagination state management with Function node and Context in Node-RED
0 reputation · 07 Jan 2022, 11:14 UTC
0 reputation · 07 Jan 2022, 11:14 UTC
A design goal is to process a large dataset in bounded chunks within a Node-RED flow. Data moves between nodes as msg objects and a Function node is intended to apply custom logic for chunking and forwarding results.
State for pagination, such as a cursor or offset, needs to persist across successive messages. The Context API provides node, flow and global scopes with memory-based or external persistent storage. Heavy computation in a Function node can block the Node.js event loop and large objects in memory context can increase memory pressure.
The decision point is which Context scope and storage mode is appropriate for pagination state when multiple messages may be in flight, and how state isolation is maintained across Function nodes in the same flow.
Which Context scope is appropriate for pagination state shared by Function nodes in a single flow? Does using flow context for a cursor introduce risk of unbounded growth with concurrent messages? What behavior should be expected for context persistence when switching between memory and file-based stores?
34775 reputation · 07 Jan 2022, 15:03 UTC
Use flow‑level context to store a pagination cursor that is shared by multiple Function nodes in the same flow. Flow context is the only scope that guarantees visibility across nodes that belong to the same flow instance.
Storing a single cursor value in flow context does not cause unbounded memory growth, but it can lead to race conditions when several messages update the same key concurrently. The last write wins, so intermediate updates may be lost. To avoid this, store per‑message state under a unique key (e.g., context.set(msg.id + ‘_cursor’, value, ‘flow’)) or use a queueing strategy.
Both stores expose the same API (context.get/set), but they differ in persistence and performance:
Switching the store type does not change how your code accesses the cursor; you simply change the contextStorage configuration in settings.js. The cursor value will survive a restart only when file‑based storage is enabled.
settings.js:
contextStorage: {
flow: {
module: "node-red-contrib-context-storage",
name: "file"
}
}var cursor = msg.payload.cursor;
context.set("paginationCursor", cursor, "flow");
return msg;var cursor = context.get("paginationCursor", "flow");
msg.payload.cursor = cursor;
return msg;var key = msg.id + "_cursor";
context.set(key, cursor, "flow");To fine‑tune the strategy, please confirm whether the flow processes messages that share the same msg.id or whether each message has a distinct identifier. This determines whether a single shared cursor or per‑message keys are required.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.