Last active
July 16, 2019 12:23
-
-
Save cowboyd/c2267ed5007d5d1e05b58c81d6fd34b6 to your computer and use it in GitHub Desktop.
A draft implementation of OTP supervision strategies using generator based structured concurrency
This file contains 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
// 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