You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The getForms.js job contain couple of anti-patterns that we can avoid by flattening the operations and break down the job into two jobs and leverage the edge condition feature on lightning. Below are couple of improvements that can simplify the job
1st - Create new input when using manualCursor
In lightning you can manually create a initial state by creating new input for any step in your workflow. This is great for specifying manual cursors for your workflow or any initial input that you want to test in your workflow. For getForms.js we have two manual cursor [cursorStart and cursorEnd] both can be specified as initial input instead of hard coding them in the job.
An example for setting up the cursor using initial state
fn(state=>{consttoday=newDate();constmonth=today.getMonth();constyear=today.getFullYear();const{ endOfMonthPrior, startOfMonthPrior }=state;state.cursorStart=startOfMonthPrior??newDate(year,month-1,1).toISOString().split('T')[0];state.cursorEnd=endOfMonthPrior??newDate(year,month,0).toISOString().split('T')[0];console.log('Cursor end:',state.cursorEnd);console.log('Cursor start:',state.cursorStart);returnstate;});// Other operations below
2nd - Avoid nested operations
Currently when fetching form list from commcare we use the callback to post the list of filtered forms to openfn inbox (Another webhook workflow in v2). This introduces a lot of ant-patterns because we have nested operations that needs to be called with state. To avoid this, we can remove the each() operation from the callback and create a new down stream job that will use the final state of getForms.js. The down stream job (We can call it postCleanedForms.js) should be triggered only if we have a list of cleaned forms
constsetOffSet=meta=>(meta?.next ? meta.limit+meta.offset : 0);fn(state=>{consttoday=newDate();constmonth=today.getMonth();constyear=today.getFullYear();const{ endOfMonthPrior, startOfMonthPrior }=state;state.cursorStart=startOfMonthPrior??newDate(year,month-1,1).toISOString().split('T')[0];state.cursorEnd=endOfMonthPrior??newDate(year,month,0).toISOString().split('T')[0];console.log('Cursor end:',state.cursorEnd);console.log('Cursor start:',state.cursorStart);returnstate;});get('/form/',{query: {limit: 200,// To update for fetching a specific number of formsoffset: setOffSet($.meta),xmlns:
'http://openrosa.org/formdesigner/34532e2a938003aae150198e2613ed2b54c410fb',// Register New Patientreceived_on_start: $.cursorStart,received_on_end: $.cursorEnd,},},state=>{const{ meta, objects }=state.data;state.meta=meta;console.log('Metadata in CommCare response for Register New Patient:');console.log(meta);state.cleanedForms=objects.filter(form=>{const{ received_on, server_modified_on }=form;constreceivedOnDate=newDate(received_on);constserverModifiedOnDate=newDate(server_modified_on);receivedOnDate.setHours(receivedOnDate.getHours(),receivedOnDate.getMinutes(),0,0);serverModifiedOnDate.setHours(serverModifiedOnDate.getHours(),serverModifiedOnDate.getMinutes(),0,0);return(receivedOnDate.toISOString()!==serverModifiedOnDate.toISOString());});if(state.cleanedForms.length>0){console.log(state.cleanedForms.length,'cleaned forms fetched...');console.log(`Posting to OpenFn Inbox...${JSON.stringify(state.cleanedForms,null,2)}`);}returnstate;});
hey @mtuchi on the 1st: we'd like to have the dynamic previous month as default cursor. I just change the order of expression to evaluate the below and the state.cursorEnd, right?
state.cursorStart =
startOfMonthPrior ??
new Date(year, month - 1, 1).toISOString().split('T')[0];
@ritazagoni if you want to use the default cursor aka new Date(year, month - 1, 1).toISoString().split('T')[0]. Then you don't need to specify state. startOfMonthPrior in your initial state.
You can simply create an input with only endOfMonth Eg
Background
The getForms.js job contain couple of anti-patterns that we can avoid by flattening the operations and break down the job into two jobs and leverage the edge condition feature on lightning. Below are couple of improvements that can simplify the job
1st - Create new input when using
manualCursor
In lightning you can manually create a initial state by creating new input for any step in your workflow. This is great for specifying manual cursors for your workflow or any initial input that you want to test in your workflow. For
getForms.js
we have two manual cursor [cursorStart
andcursorEnd
] both can be specified as initial input instead of hard coding them in the job.An example for setting up the cursor using initial state
2nd - Avoid nested operations
Currently when fetching form list from
commcare
we use the callback to post the list of filtered forms to openfn inbox (Another webhook workflow in v2). This introduces a lot of ant-patterns because we have nested operations that needs to be called withstate
. To avoid this, we can remove theeach()
operation from the callback and create a new down stream job that will use the final state ofgetForms.js
. The down stream job (We can call itpostCleanedForms.js
) should be triggered only if we have a list of cleaned formsFlattened getForms.js job
㊙️ state.json
👨🏽💻 getForms.js | [email protected]
Edge condition
state.cleanedForms.length > 0
postCleanedForms.js
🌵 state.json
postCleanedForms.js | [email protected]
workflow.json for getForms and postCleanedForms steps
The text was updated successfully, but these errors were encountered: