Core Technical Concepts
Context Propagation
Every migration requires ability to work on different levels simultaneously:
- repository - clone, branch, commit, push
- directories - iterate, copy, move, remove
- files - iterate, copy, move, remove
- code blocks - iterate, change, remove
You need ability to jump between those levels quickly. Child level should be able to access data from parent level. Core principle in workflow engine is passing context. We are using Asyncronous Context Tracking to able to pass context between function calls. When you run a function within context, it will be propagated down to all other function calls. Similar how React context is getting passed down to all the children components.
Context is getting passed inside function’s chain calls and also inside callback. Let’s look at simple example:
Saving and Reusing Context
Function calls with context can be saved and reused:
Callback Context Retrieval
Another option to retrieve parent context is inside callback function:
Plugin Creation
Thanks to callback context retrieval, plugins can be created as functions:
Remote Execution
Passing context and ability to retrieve it will open for us more interesting possibilities. We can wrap every function with higher order function and make child call in different process or even different server.
Chain Calls
Another interesting feature is ability to retrieve some data from chain calls and use it later. For example we can retrieve all usages of console.log
in our codebase:
There are a lot of scenarios that require such logic during code refactoring.
Most of the functions will have 2 arguments:
- actual function parameters
- callback that will have context inside (optional)
Promises vs Futures
In JavaScript every promise you instantiate is getting called immediately. For example
In workflow engine we are using lazy promises aka futures, which are getting executed when await
operator is used.
That is important because it will allow us save context and postpone execution to the future.
That should help you better structure code and parallelize tasks. It is recommended to use await
whenever you need execute tasks, otherwise just save links to task execution flow and use it later: const repo1Packages = git.clone('repo1').dirs('packages/*')
is definition of flow, not actual execution.
Types and chain calls
Every function is typed and has jsdoc description.
Every function will return lazy promise object with helpers. Once you await
lazy promise - it will also return helpers. Return is typed and you will get helpers that are currently available.
Once you type repoLink.
- you will get autocomplete in your IDE with list of possible functions.
Current working directory context
Current working directory is also propagated between function calls. You can call getCwdContext() anytime and get directory. Here is how it works in details:
Was this page helpful?