supervisor_machines 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Cargo.lock +3 -2
- data/ext/supervisor_machines_native/core/Cargo.toml +1 -1
- data/ext/supervisor_machines_native/core/src/supervisor.rs +52 -0
- data/ext/supervisor_machines_native/ffi/Cargo.toml +13 -1
- data/ext/supervisor_machines_native/ffi/src/decider.rs +23 -0
- data/lib/supervisor_machines/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f36d17f94d2e12b476ab45bf7bf3d4e0f2ff0b7f936866fe110802dec8d7cb74
|
|
4
|
+
data.tar.gz: 9514f57779388f9574596178e9812b71873ae8a40630c91a98c821bad3f03347
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3aeac1b644cc8ea8e9ec41748b44c9e541a8be0ac5287b73e6047aa598d146542a8e6a3312d96e07af93ab05bb5be483dcbe5110910897912578b77d248514d3
|
|
7
|
+
data.tar.gz: 4d8fd693df515ced5543be1a6e15a5b12ea1162deb27f9d71996aaf8cef1a805d93162b130fa88254dc771a6596b5c7f962dfa4cd682815dccdf532e4533480e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.3](https://github.com/seuros/supervisor_machines/compare/supervisor_machines/v0.1.2...supervisor_machines/v0.1.3) (2026-11-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* enable the rb-sys compiled fallback so new Rubies can build ([ef51e18](https://github.com/seuros/supervisor_machines/commit/ef51e18b3fe96522ce56ace91d93055e33996e78))
|
|
9
|
+
* raise the chrono_machines floor to 0.12.1 ([20b6538](https://github.com/seuros/supervisor_machines/commit/20b6538967c3e6bde705c8822d3a53ad6a07a1f6))
|
|
10
|
+
|
|
11
|
+
## [0.1.2](https://github.com/seuros/supervisor_machines/compare/supervisor_machines/v0.1.1...supervisor_machines/v0.1.2) (2026-11-01)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* back off granted restarts by recent restart count ([e7532e8](https://github.com/seuros/supervisor_machines/commit/e7532e8e98e43171c8d76f176161fdea50403a27))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Bug Fixes
|
|
20
|
+
|
|
21
|
+
* a republished platform gem is skipped, not fatal ([39160e7](https://github.com/seuros/supervisor_machines/commit/39160e7e295d58500d846fb56d190eff6e803151))
|
|
22
|
+
|
|
3
23
|
## [0.1.1](https://github.com/seuros/supervisor_machines/compare/supervisor_machines-v0.1.0...supervisor_machines/v0.1.1) (2026-11-01)
|
|
4
24
|
|
|
5
25
|
|
data/Cargo.lock
CHANGED
|
@@ -252,13 +252,14 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|
|
252
252
|
|
|
253
253
|
[[package]]
|
|
254
254
|
name = "supervisor-machines"
|
|
255
|
-
version = "0.
|
|
255
|
+
version = "0.3.0"
|
|
256
256
|
|
|
257
257
|
[[package]]
|
|
258
258
|
name = "supervisor_machines_native"
|
|
259
|
-
version = "0.1.
|
|
259
|
+
version = "0.1.2"
|
|
260
260
|
dependencies = [
|
|
261
261
|
"magnus",
|
|
262
|
+
"rb-sys",
|
|
262
263
|
"supervisor-machines",
|
|
263
264
|
]
|
|
264
265
|
|
|
@@ -97,6 +97,58 @@ impl<const CHILDREN: usize, const HISTORY: usize> Supervisor<CHILDREN, HISTORY>
|
|
|
97
97
|
counted
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/// How long to hold off the restart just granted: `base_ns` doubled once
|
|
101
|
+
/// per restart already inside the window, capped at `ceiling_ns`.
|
|
102
|
+
///
|
|
103
|
+
/// Neither OTP nor [`stopped`](Self::stopped) imposes a delay, so a
|
|
104
|
+
/// supervisor that restarts the moment a child dies spends its whole
|
|
105
|
+
/// intensity budget in the time it takes to fail that many times. For a
|
|
106
|
+
/// child that dies while being constructed that is well under a
|
|
107
|
+
/// millisecond, and the window the intensity was written for never gets to
|
|
108
|
+
/// mean anything. Waiting this long between the decision and the restart
|
|
109
|
+
/// spreads the budget back over that window.
|
|
110
|
+
///
|
|
111
|
+
/// The count decays as the window slides, so a child that settles returns
|
|
112
|
+
/// to `base_ns` on its own. Jitter is the caller's to add.
|
|
113
|
+
///
|
|
114
|
+
/// ```
|
|
115
|
+
/// use supervisor_machines::{Exit, Intensity, Policy, Strategy, Supervisor};
|
|
116
|
+
///
|
|
117
|
+
/// const MS: u64 = 1_000_000;
|
|
118
|
+
///
|
|
119
|
+
/// let mut tree: Supervisor<1, 8> = Supervisor::new(
|
|
120
|
+
/// Strategy::OneForOne,
|
|
121
|
+
/// Intensity::new(5, 60_000 * MS),
|
|
122
|
+
/// );
|
|
123
|
+
///
|
|
124
|
+
/// // The first restart waits the base, each further one twice as long.
|
|
125
|
+
/// tree.stopped(0, Policy::Permanent, Exit::Abnormal, 0);
|
|
126
|
+
/// assert_eq!(tree.restart_delay_ns(100 * MS, 10_000 * MS, 0), 100 * MS);
|
|
127
|
+
///
|
|
128
|
+
/// tree.stopped(0, Policy::Permanent, Exit::Abnormal, MS);
|
|
129
|
+
/// assert_eq!(tree.restart_delay_ns(100 * MS, 10_000 * MS, MS), 200 * MS);
|
|
130
|
+
///
|
|
131
|
+
/// // Once the window has slid past them the delay is back to the base.
|
|
132
|
+
/// assert_eq!(
|
|
133
|
+
/// tree.restart_delay_ns(100 * MS, 10_000 * MS, 120_000 * MS),
|
|
134
|
+
/// 100 * MS,
|
|
135
|
+
/// );
|
|
136
|
+
/// ```
|
|
137
|
+
#[must_use]
|
|
138
|
+
pub const fn restart_delay_ns(&self, base_ns: u64, ceiling_ns: u64, now_ns: u64) -> u64 {
|
|
139
|
+
let mut delay = base_ns;
|
|
140
|
+
let mut doublings = self.recent_restarts(now_ns).saturating_sub(1);
|
|
141
|
+
while doublings > 0 && delay < ceiling_ns {
|
|
142
|
+
delay = delay.saturating_mul(2);
|
|
143
|
+
doublings -= 1;
|
|
144
|
+
}
|
|
145
|
+
if delay > ceiling_ns {
|
|
146
|
+
ceiling_ns
|
|
147
|
+
} else {
|
|
148
|
+
delay
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
100
152
|
/// The children a failure at `index` takes with it under this strategy.
|
|
101
153
|
#[must_use]
|
|
102
154
|
pub const fn span(&self, index: usize) -> Span {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "supervisor_machines_native"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
edition.workspace = true
|
|
5
5
|
rust-version.workspace = true
|
|
6
6
|
authors = ["Abdelkader Boudih <oss@seuros.com>"]
|
|
@@ -17,3 +17,15 @@ workspace = true
|
|
|
17
17
|
[dependencies]
|
|
18
18
|
supervisor-machines = { workspace = true, features = ["std"] }
|
|
19
19
|
magnus = { version = ">= 0.9.3", default-features = false, features = ["io"] }
|
|
20
|
+
# Nothing here calls rb-sys directly: this is the compiled fallback that
|
|
21
|
+
# implements the stable API for a Ruby rb-sys has no pre-generated bindings
|
|
22
|
+
# for, such as a preview. magnus asks for "stable-api" without it, and
|
|
23
|
+
# default-features = false drops the default that would have supplied it, so
|
|
24
|
+
# removing this line breaks the build on every future Ruby.
|
|
25
|
+
# Nothing here calls rb-sys directly: this is the compiled fallback that
|
|
26
|
+
# implements the stable API for a Ruby rb-sys ships no pre-generated bindings
|
|
27
|
+
# for, such as a preview. magnus asks for "stable-api" without it, and its
|
|
28
|
+
# default-features = false drops the default that would have supplied it, so
|
|
29
|
+
# dropping this line breaks the build on every Ruby newer than rb-sys.
|
|
30
|
+
rb-sys = { version = ">= 0.9.130", default-features = false, features = ["stable-api-compiled-fallback"] }
|
|
31
|
+
|
|
@@ -30,6 +30,7 @@ trait Decide: Send {
|
|
|
30
30
|
fn strategy(&self) -> Strategy;
|
|
31
31
|
fn terminated(&self) -> bool;
|
|
32
32
|
fn recent_restarts(&self, now_ns: u64) -> u32;
|
|
33
|
+
fn restart_delay_ns(&self, base_ns: u64, ceiling_ns: u64, now_ns: u64) -> u64;
|
|
33
34
|
fn stopped(&mut self, index: usize, policy: Policy, exit: Exit, now_ns: u64) -> Decision;
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -54,6 +55,10 @@ impl<const CHILDREN: usize> Decide for Shape<CHILDREN> {
|
|
|
54
55
|
self.0.recent_restarts(now_ns)
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
fn restart_delay_ns(&self, base_ns: u64, ceiling_ns: u64, now_ns: u64) -> u64 {
|
|
59
|
+
self.0.restart_delay_ns(base_ns, ceiling_ns, now_ns)
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
fn stopped(&mut self, index: usize, policy: Policy, exit: Exit, now_ns: u64) -> Decision {
|
|
58
63
|
self.0.stopped(index, policy, exit, now_ns)
|
|
59
64
|
}
|
|
@@ -164,6 +169,23 @@ impl Wrapper {
|
|
|
164
169
|
self.0.borrow().recent_restarts(now_ns)
|
|
165
170
|
}
|
|
166
171
|
|
|
172
|
+
/// How long to hold off a granted restart, backing off per restart already
|
|
173
|
+
/// inside the window.
|
|
174
|
+
fn restart_delay_ns(rb_self: &Self, args: &[Value]) -> Result<u64, Error> {
|
|
175
|
+
let args = scan_args::<(), (), (), (), RHash, ()>(args)?;
|
|
176
|
+
let (Whole(base_ns), Whole(ceiling_ns), Whole(now_ns)) =
|
|
177
|
+
get_kwargs::<_, (Whole<u64>, Whole<u64>, Whole<u64>), (), ()>(
|
|
178
|
+
args.keywords,
|
|
179
|
+
&["base_ns", "ceiling_ns", "now_ns"],
|
|
180
|
+
&[],
|
|
181
|
+
)?
|
|
182
|
+
.required;
|
|
183
|
+
Ok(rb_self
|
|
184
|
+
.0
|
|
185
|
+
.borrow()
|
|
186
|
+
.restart_delay_ns(base_ns, ceiling_ns, now_ns))
|
|
187
|
+
}
|
|
188
|
+
|
|
167
189
|
fn inspect(ruby: &Ruby, rb_self: &Self) -> String {
|
|
168
190
|
format!(
|
|
169
191
|
"#<SupervisorMachines::Decider strategy={} children={} terminated={}>",
|
|
@@ -185,6 +207,7 @@ pub fn define(ruby: &Ruby, module: RModule) -> Result<(), Error> {
|
|
|
185
207
|
class.define_method("strategy", method!(Wrapper::strategy, 0))?;
|
|
186
208
|
class.define_method("terminated?", method!(Wrapper::terminated, 0))?;
|
|
187
209
|
class.define_method("recent_restarts", method!(Wrapper::recent_restarts, 1))?;
|
|
210
|
+
class.define_method("restart_delay_ns", method!(Wrapper::restart_delay_ns, -1))?;
|
|
188
211
|
class.define_method("inspect", method!(Wrapper::inspect, 0))?;
|
|
189
212
|
Ok(())
|
|
190
213
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: supervisor_machines
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Abdelkader Boudih
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
18
|
+
version: 0.12.1
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
25
|
+
version: 0.12.1
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: deadline_machines
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|