Closed qianl15 closed 2 months ago
cc @demetris-manikas
Can someone please clarify about which JSON.stringify/parse pair is this about? I guess (https://github.com/dbos-inc/dbos-transact/blob/8e9d254a4b7852196c1f4dea91d0aeaf77b8c984/src/workflow.ts#L210) and (https://github.com/dbos-inc/dbos-transact/blob/8e9d254a4b7852196c1f4dea91d0aeaf77b8c984/src/workflow.ts#L159) but not sure.
We need to add replacer and reviver whenever we record/retrieve stored inputs/outputs.
JSON.stringify(args, DBOSReplacer)
and JSON.parse(rows[0].inputs, DBOSReviver)
. But we should also use them when we record workflow and operation outputs. There are several places where we use JSON.parse(output)
and JSON.stringify(output)
and we should update all of them.JSON.stringify(output)
, and in checkExecution we use JSON.parse(rows[1].output)
. JSON.parse(rows[0].output)
to use the Reviver.I got a POC on this using lodash for deep cloning.
json.stringify.parse.txt
The prefix should definitely be something other than date:
but at least it's working
Let me know if this kind of solution is viable.
The script also demonstrates that there is no way of telling if a value is a Date in the JSON.stringify replacer
Forgot to mention.
To run the POC drop the file in the root directory of the project
Rename it to .js
Run npm install lodash
Run node json.stringify.parse
I think you'll be able to get the actual object by using this[key]
instead of value
in a replacer function. Source: https://stackoverflow.com/a/54037861
As a function, it takes two parameters: the key and the value being stringified. The object in which the key was found is provided as the replacer's this context.
Here's an example to use the replacer in our case (based on the code you provided):
let obj = {
num: '2',
dates: {
date1: new Date(2023, 10, 2, 23, 12, 200),
date2: new Date(2024, 4, 1, 13, 11, 223)
}
}
var replacer = function(key, value) {
console.log(this[key])
console.log(typeof this[key]) // This will be Object for a Date value
console.log(typeof value) // This will be string for a Date value
console.log(Object.prototype.toString.call(this[key]) === '[object Date]') // This will be true for a Date value
if (this[key] instanceof Date) { // or we can use Object.prototype.toString.call(this[key]) === '[object Date]'
return 'date:' + this[key].toUTCString();
}
return value;
}
let str = JSON.stringify(obj, replacer);
console.log(str)
Addressed in https://github.com/dbos-inc/dbos-transact/pull/490
The problem is when we run JSON.stringify the Date will be converted into string, and when we try to recover workflow or replay a workflow there's no way to deserialize it back to Date.
We need to handle Date type in the DBOSReplacer and DBOSReviver https://github.com/dbos-inc/dbos-transact/blob/main/src/utils.ts So we can properly serialize and deserialize date. Then use the Replacer and Reviver everywhere we use JSON.stringify() and JSON.parse()