Skip to content

Instantly share code, notes, and snippets.

@cowboyd
Last active July 16, 2019 12:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cowboyd/c2267ed5007d5d1e05b58c81d6fd34b6 to your computer and use it in GitHub Desktop.
Save cowboyd/c2267ed5007d5d1e05b58c81d6fd34b6 to your computer and use it in GitHub Desktop.
A draft implementation of OTP supervision strategies using generator based structured concurrency
// implementation of Erlang genserver restart strategies on supervisor
// http://erlang.org/doc/design_principles/sup_princ.html#one_for_one
//
// For demonstration purposes, the maximum restart intesity logic has been
// omitted. However, it would be straightforward to check restart intesity
// inside each catch block and use it to determine if the error should be
// instead rethrown.
/**
* one_for_one - If one child process terminates and is to be
* restarted, only that child process is affected. This is the default
* restart strategy.
*
* http://erlang.org/doc/design_principles/sup_princ.html#one_for_one
**/
export function oneForOne(children) {
return function() {
children.forEach(child => {
this.fork(function*() {
restart:
try {
yield child;
} catch (e) {
break restart;
}
});
});
};
}
/**
* one_for_all - If one child process terminates and is to be
* restarted, all other child processes are terminated and then all
* child processes are restarted.
*
* http://erlang.org/doc/design_principles/sup_princ.html#one_for_all
*/
export function oneForAll(children) {
return function*() {
restart:
try {
yield function() {
children.forEach(child => this.fork(child));
};
} catch (e) {
break restart;
}
};
}
/**
* rest_for_one - If a child process terminates, the rest of the child
* processes (that is, the child processes after the terminated
* process in start order) are terminated. Then the terminated child
* process and the rest of the child processes are restarted.
*
* http://erlang.org/doc/design_principles/sup_princ.html#rest_for_one
*/
export function restForOne(children = []) {
if (children.length === 0) {
return function*() {};
}
return function*() {
let [first, ...rest] = children;
this.fork(first);
restart:
try {
yield restForOne(rest);
} catch (e) {
break restart;
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment