-
Notifications
You must be signed in to change notification settings - Fork 14
Limit state size in runtime #1209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
3e06c57
runtime: add function to ensure that state size does not exceed a par…
josephjclark d2a228a
add new stateLimit_mb option
josephjclark d8cde31
engine: support state limit mb as an option
josephjclark 06f0002
refactor rutime option
josephjclark 582b8db
tidying up
josephjclark 643d625
fix failing test in mock
josephjclark 3dfc4ee
more generous timeout on flaky test
josephjclark 12fa6b8
add debug log
josephjclark f2968bc
changeset
josephjclark 9feaa73
tweak memory limit
josephjclark 1548e62
refine options
josephjclark 8f774dd
runtime: type safety
josephjclark File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| --- | ||
| '@openfn/engine-multi': minor | ||
| '@openfn/ws-worker': minor | ||
| '@openfn/runtime': minor | ||
| --- | ||
|
|
||
| Measure the size of state objects at the end of each step, and throw if they exceed a limit | ||
|
|
||
| In the Worker, this limit is set to 25% of the available runtime memory. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,4 @@ | ||
| import type { State } from '@openfn/lexicon'; | ||
| import stringify from 'fast-safe-stringify'; | ||
|
|
||
| // TODO I'm in the market for the best solution here - immer? deep-clone? | ||
| // What should we do if functions are in the state? | ||
| export default (state: State) => JSON.parse(stringify(state)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { JsonStreamStringify } from 'json-stream-stringify'; | ||
| import { StateTooLargeError } from '../errors'; | ||
|
|
||
| const replacer = (_key: string, value: any) => { | ||
| // Ignore non serializable keys | ||
| if ( | ||
| value === undefined || | ||
| typeof value === 'function' || | ||
| value?.constructor?.name === 'Promise' | ||
| ) { | ||
| return undefined; | ||
| } | ||
|
|
||
| return value; | ||
| }; | ||
|
|
||
| // throws if state exceeds a particular size limit | ||
| export default async (value: any, limit_mb: number = 500) => { | ||
| if (value && !isNaN(limit_mb) && limit_mb > 0) { | ||
| const limitBytes = limit_mb * 1024 * 1024; | ||
| let size_bytes = 0; | ||
| const stream = new JsonStreamStringify(value, replacer, 0, true); | ||
| for await (const chunk of stream) { | ||
| // Each chunk is a string token from the JSON output | ||
| size_bytes += Buffer.byteLength(chunk, 'utf8'); | ||
|
|
||
| if (size_bytes > limitBytes) { | ||
| stream.destroy(); | ||
| throw new StateTooLargeError(limit_mb); | ||
| } | ||
| } | ||
| stream.destroy(); | ||
| } | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently set in the engine and worker with different rules!
Maybe the worker just passes in a fixed value, if it has one, and the engine defaults to a % of runtime memory. That's probably cleanest.