ominfra 0.0.0.dev118__py3-none-any.whl → 0.0.0.dev120__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,31 +1,25 @@
1
- #!/usr/bin/env python3
2
1
  # ruff: noqa: UP006 UP007
3
- # @omlish-amalg ../scripts/supervisor.py
4
- import json
5
- import logging
6
2
  import signal
7
3
  import time
8
4
  import typing as ta
9
5
 
6
+ from omlish.lite.cached import cached_nullary
10
7
  from omlish.lite.check import check_not_none
11
- from omlish.lite.logs import configure_standard_logging
12
- from omlish.lite.marshal import unmarshal_obj
8
+ from omlish.lite.logs import log
13
9
 
14
10
  from .compat import ExitNow
15
11
  from .compat import as_string
16
12
  from .compat import decode_wait_status
17
13
  from .compat import signame
18
14
  from .configs import ProcessGroupConfig
19
- from .configs import ServerConfig
20
15
  from .context import ServerContext
21
16
  from .dispatchers import Dispatcher
17
+ from .events import EVENT_CALLBACKS
22
18
  from .events import TICK_EVENTS
23
19
  from .events import ProcessGroupAddedEvent
24
20
  from .events import ProcessGroupRemovedEvent
25
21
  from .events import SupervisorRunningEvent
26
22
  from .events import SupervisorStoppingEvent
27
- from .events import clear_events
28
- from .events import notify_event
29
23
  from .process import ProcessGroup
30
24
  from .process import Subprocess
31
25
  from .states import SupervisorState
@@ -33,7 +27,8 @@ from .states import SupervisorStates
33
27
  from .states import get_process_state_description
34
28
 
35
29
 
36
- log = logging.getLogger(__name__)
30
+ def timeslice(period: int, when: float) -> int:
31
+ return int(when - (when % period))
37
32
 
38
33
 
39
34
  class Supervisor:
@@ -48,6 +43,8 @@ class Supervisor:
48
43
  self._stopping = False # set after we detect that we are handling a stop request
49
44
  self._last_shutdown_report = 0. # throttle for delayed process error reports at stop
50
45
 
46
+ #
47
+
51
48
  @property
52
49
  def context(self) -> ServerContext:
53
50
  return self._context
@@ -55,47 +52,14 @@ class Supervisor:
55
52
  def get_state(self) -> SupervisorState:
56
53
  return self._context.state
57
54
 
58
- def main(self) -> None:
59
- if not self._context.first:
60
- # prevent crash on libdispatch-based systems, at least for the first request
61
- self._context.cleanup_fds()
62
-
63
- self._context.set_uid_or_exit()
55
+ #
64
56
 
65
- if self._context.first:
66
- self._context.set_rlimits_or_exit()
67
-
68
- # this sets the options.logger object delay logger instantiation until after setuid
69
- if not self._context.config.nocleanup:
70
- # clean up old automatic logs
71
- self._context.clear_auto_child_logdir()
72
-
73
- self.run()
74
-
75
- def run(self) -> None:
76
- self._process_groups = {} # clear
77
- self._stop_groups = None # clear
78
-
79
- clear_events()
80
-
81
- try:
82
- for config in self._context.config.groups or []:
83
- self.add_process_group(config)
84
-
85
- self._context.set_signals()
86
-
87
- if not self._context.config.nodaemon and self._context.first:
88
- self._context.daemonize()
89
-
90
- # writing pid file needs to come *after* daemonizing or pid will be wrong
91
- self._context.write_pidfile()
57
+ class DiffToActive(ta.NamedTuple):
58
+ added: ta.List[ProcessGroupConfig]
59
+ changed: ta.List[ProcessGroupConfig]
60
+ removed: ta.List[ProcessGroupConfig]
92
61
 
93
- self.runforever()
94
-
95
- finally:
96
- self._context.cleanup()
97
-
98
- def diff_to_active(self):
62
+ def diff_to_active(self) -> DiffToActive:
99
63
  new = self._context.config.groups or []
100
64
  cur = [group.config for group in self._process_groups.values()]
101
65
 
@@ -107,7 +71,7 @@ class Supervisor:
107
71
 
108
72
  changed = [cand for cand in new if cand != curdict.get(cand.name, cand)]
109
73
 
110
- return added, changed, removed
74
+ return Supervisor.DiffToActive(added, changed, removed)
111
75
 
112
76
  def add_process_group(self, config: ProcessGroupConfig) -> bool:
113
77
  name = config.name
@@ -117,7 +81,7 @@ class Supervisor:
117
81
  group = self._process_groups[name] = ProcessGroup(config, self._context)
118
82
  group.after_setuid()
119
83
 
120
- notify_event(ProcessGroupAddedEvent(name))
84
+ EVENT_CALLBACKS.notify(ProcessGroupAddedEvent(name))
121
85
  return True
122
86
 
123
87
  def remove_process_group(self, name: str) -> bool:
@@ -128,7 +92,7 @@ class Supervisor:
128
92
 
129
93
  del self._process_groups[name]
130
94
 
131
- notify_event(ProcessGroupRemovedEvent(name))
95
+ EVENT_CALLBACKS.notify(ProcessGroupRemovedEvent(name))
132
96
  return True
133
97
 
134
98
  def get_process_map(self) -> ta.Dict[int, Dispatcher]:
@@ -157,6 +121,72 @@ class Supervisor:
157
121
 
158
122
  return unstopped
159
123
 
124
+ #
125
+
126
+ def main(self) -> None:
127
+ self.setup()
128
+ self.run()
129
+
130
+ @cached_nullary
131
+ def setup(self) -> None:
132
+ if not self._context.first:
133
+ # prevent crash on libdispatch-based systems, at least for the first request
134
+ self._context.cleanup_fds()
135
+
136
+ self._context.set_uid_or_exit()
137
+
138
+ if self._context.first:
139
+ self._context.set_rlimits_or_exit()
140
+
141
+ # this sets the options.logger object delay logger instantiation until after setuid
142
+ if not self._context.config.nocleanup:
143
+ # clean up old automatic logs
144
+ self._context.clear_auto_child_logdir()
145
+
146
+ def run(
147
+ self,
148
+ *,
149
+ callback: ta.Optional[ta.Callable[['Supervisor'], bool]] = None,
150
+ ) -> None:
151
+ self._process_groups = {} # clear
152
+ self._stop_groups = None # clear
153
+
154
+ EVENT_CALLBACKS.clear()
155
+
156
+ try:
157
+ for config in self._context.config.groups or []:
158
+ self.add_process_group(config)
159
+
160
+ self._context.set_signals()
161
+
162
+ if not self._context.config.nodaemon and self._context.first:
163
+ self._context.daemonize()
164
+
165
+ # writing pid file needs to come *after* daemonizing or pid will be wrong
166
+ self._context.write_pidfile()
167
+
168
+ EVENT_CALLBACKS.notify(SupervisorRunningEvent())
169
+
170
+ while True:
171
+ if callback is not None and not callback(self):
172
+ break
173
+
174
+ self._run_once()
175
+
176
+ finally:
177
+ self._context.cleanup()
178
+
179
+ #
180
+
181
+ def _run_once(self) -> None:
182
+ self._poll()
183
+ self._reap()
184
+ self._handle_signal()
185
+ self._tick()
186
+
187
+ if self._context.state < SupervisorStates.RUNNING:
188
+ self._ordered_stop_groups_phase_2()
189
+
160
190
  def _ordered_stop_groups_phase_1(self) -> None:
161
191
  if self._stop_groups:
162
192
  # stop the last group (the one with the "highest" priority)
@@ -173,110 +203,77 @@ class Supervisor:
173
203
  # down, so push it back on to the end of the stop group queue
174
204
  self._stop_groups.append(group)
175
205
 
176
- def runforever(self) -> None:
177
- notify_event(SupervisorRunningEvent())
178
- timeout = 1 # this cannot be fewer than the smallest TickEvent (5)
179
-
180
- while True:
181
- combined_map = {}
182
- combined_map.update(self.get_process_map())
183
-
184
- pgroups = list(self._process_groups.values())
185
- pgroups.sort()
186
-
187
- if self._context.state < SupervisorStates.RUNNING:
188
- if not self._stopping:
189
- # first time, set the stopping flag, do a notification and set stop_groups
190
- self._stopping = True
191
- self._stop_groups = pgroups[:]
192
- notify_event(SupervisorStoppingEvent())
193
-
194
- self._ordered_stop_groups_phase_1()
195
-
196
- if not self.shutdown_report():
197
- # if there are no unstopped processes (we're done killing everything), it's OK to shutdown or reload
198
- raise ExitNow
199
-
200
- for fd, dispatcher in combined_map.items():
201
- if dispatcher.readable():
202
- self._context.poller.register_readable(fd)
203
- if dispatcher.writable():
204
- self._context.poller.register_writable(fd)
205
-
206
- r, w = self._context.poller.poll(timeout)
207
-
208
- for fd in r:
209
- if fd in combined_map:
210
- try:
211
- dispatcher = combined_map[fd]
212
- log.debug('read event caused by %r', dispatcher)
213
- dispatcher.handle_read_event()
214
- if not dispatcher.readable():
215
- self._context.poller.unregister_readable(fd)
216
- except ExitNow:
217
- raise
218
- except Exception: # noqa
219
- combined_map[fd].handle_error()
220
- else:
221
- # if the fd is not in combined_map, we should unregister it. otherwise, it will be polled every
222
- # time, which may cause 100% cpu usage
223
- log.debug('unexpected read event from fd %r', fd)
224
- try:
225
- self._context.poller.unregister_readable(fd)
226
- except Exception: # noqa
227
- pass
228
-
229
- for fd in w:
230
- if fd in combined_map:
231
- try:
232
- dispatcher = combined_map[fd]
233
- log.debug('write event caused by %r', dispatcher)
234
- dispatcher.handle_write_event()
235
- if not dispatcher.writable():
236
- self._context.poller.unregister_writable(fd)
237
- except ExitNow:
238
- raise
239
- except Exception: # noqa
240
- combined_map[fd].handle_error()
241
- else:
242
- log.debug('unexpected write event from fd %r', fd)
243
- try:
244
- self._context.poller.unregister_writable(fd)
245
- except Exception: # noqa
246
- pass
247
-
248
- for group in pgroups:
249
- group.transition()
206
+ def _poll(self) -> None:
207
+ combined_map = {}
208
+ combined_map.update(self.get_process_map())
250
209
 
251
- self._reap()
252
- self._handle_signal()
253
- self._tick()
210
+ pgroups = list(self._process_groups.values())
211
+ pgroups.sort()
254
212
 
255
- if self._context.state < SupervisorStates.RUNNING:
256
- self._ordered_stop_groups_phase_2()
213
+ if self._context.state < SupervisorStates.RUNNING:
214
+ if not self._stopping:
215
+ # first time, set the stopping flag, do a notification and set stop_groups
216
+ self._stopping = True
217
+ self._stop_groups = pgroups[:]
218
+ EVENT_CALLBACKS.notify(SupervisorStoppingEvent())
257
219
 
258
- if self._context.test:
259
- break
220
+ self._ordered_stop_groups_phase_1()
260
221
 
261
- def _tick(self, now: ta.Optional[float] = None) -> None:
262
- """Send one or more 'tick' events when the timeslice related to the period for the event type rolls over"""
263
-
264
- if now is None:
265
- # now won't be None in unit tests
266
- now = time.time()
222
+ if not self.shutdown_report():
223
+ # if there are no unstopped processes (we're done killing everything), it's OK to shutdown or reload
224
+ raise ExitNow
267
225
 
268
- for event in TICK_EVENTS:
269
- period = event.period # type: ignore
226
+ for fd, dispatcher in combined_map.items():
227
+ if dispatcher.readable():
228
+ self._context.poller.register_readable(fd)
229
+ if dispatcher.writable():
230
+ self._context.poller.register_writable(fd)
270
231
 
271
- last_tick = self._ticks.get(period)
272
- if last_tick is None:
273
- # we just started up
274
- last_tick = self._ticks[period] = timeslice(period, now)
232
+ timeout = 1 # this cannot be fewer than the smallest TickEvent (5)
233
+ r, w = self._context.poller.poll(timeout)
234
+
235
+ for fd in r:
236
+ if fd in combined_map:
237
+ try:
238
+ dispatcher = combined_map[fd]
239
+ log.debug('read event caused by %r', dispatcher)
240
+ dispatcher.handle_read_event()
241
+ if not dispatcher.readable():
242
+ self._context.poller.unregister_readable(fd)
243
+ except ExitNow:
244
+ raise
245
+ except Exception: # noqa
246
+ combined_map[fd].handle_error()
247
+ else:
248
+ # if the fd is not in combined_map, we should unregister it. otherwise, it will be polled every
249
+ # time, which may cause 100% cpu usage
250
+ log.debug('unexpected read event from fd %r', fd)
251
+ try:
252
+ self._context.poller.unregister_readable(fd)
253
+ except Exception: # noqa
254
+ pass
255
+
256
+ for fd in w:
257
+ if fd in combined_map:
258
+ try:
259
+ dispatcher = combined_map[fd]
260
+ log.debug('write event caused by %r', dispatcher)
261
+ dispatcher.handle_write_event()
262
+ if not dispatcher.writable():
263
+ self._context.poller.unregister_writable(fd)
264
+ except ExitNow:
265
+ raise
266
+ except Exception: # noqa
267
+ combined_map[fd].handle_error()
268
+ else:
269
+ log.debug('unexpected write event from fd %r', fd)
270
+ try:
271
+ self._context.poller.unregister_writable(fd)
272
+ except Exception: # noqa
273
+ pass
275
274
 
276
- this_tick = timeslice(period, now)
277
- if this_tick != last_tick:
278
- self._ticks[period] = this_tick
279
- notify_event(event(this_tick, self))
275
+ for group in pgroups:
276
+ group.transition()
280
277
 
281
278
  def _reap(self, *, once: bool = False, depth: int = 0) -> None:
282
279
  if depth >= 100:
@@ -326,51 +323,22 @@ class Supervisor:
326
323
  else:
327
324
  log.debug('received %s indicating nothing', signame(sig))
328
325
 
326
+ def _tick(self, now: ta.Optional[float] = None) -> None:
327
+ """Send one or more 'tick' events when the timeslice related to the period for the event type rolls over"""
329
328
 
330
- def timeslice(period, when):
331
- return int(when - (when % period))
332
-
333
-
334
- def main(args=None, test=False):
335
- import argparse
336
-
337
- parser = argparse.ArgumentParser()
338
- parser.add_argument('config_file', metavar='config-file')
339
- args = parser.parse_args()
340
-
341
- configure_standard_logging('INFO')
342
-
343
- if not (cf := args.config_file):
344
- raise RuntimeError('No config file specified')
345
-
346
- # if we hup, restart by making a new Supervisor()
347
- first = True
348
- while True:
349
- with open(cf) as f:
350
- config_src = f.read()
351
- config_dct = json.loads(config_src)
352
- config: ServerConfig = unmarshal_obj(config_dct, ServerConfig)
353
-
354
- context = ServerContext(
355
- config,
356
- )
357
-
358
- context.first = first
359
- context.test = test
360
- go(context)
361
- # options.close_logger()
362
- first = False
363
- if test or (context.state < SupervisorStates.RESTARTING):
364
- break
365
-
329
+ if now is None:
330
+ # now won't be None in unit tests
331
+ now = time.time()
366
332
 
367
- def go(context): # pragma: no cover
368
- d = Supervisor(context)
369
- try:
370
- d.main()
371
- except ExitNow:
372
- pass
333
+ for event in TICK_EVENTS:
334
+ period = event.period # type: ignore
373
335
 
336
+ last_tick = self._ticks.get(period)
337
+ if last_tick is None:
338
+ # we just started up
339
+ last_tick = self._ticks[period] = timeslice(period, now)
374
340
 
375
- if __name__ == '__main__':
376
- main()
341
+ this_tick = timeslice(period, now)
342
+ if this_tick != last_tick:
343
+ self._ticks[period] = this_tick
344
+ EVENT_CALLBACKS.notify(event(this_tick, self))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev118
3
+ Version: 0.0.0.dev120
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,8 +12,8 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Operating System :: POSIX
13
13
  Requires-Python: >=3.12
14
14
  License-File: LICENSE
15
- Requires-Dist: omdev ==0.0.0.dev118
16
- Requires-Dist: omlish ==0.0.0.dev118
15
+ Requires-Dist: omdev ==0.0.0.dev120
16
+ Requires-Dist: omlish ==0.0.0.dev120
17
17
  Provides-Extra: all
18
18
  Requires-Dist: paramiko ~=3.5 ; extra == 'all'
19
19
  Requires-Dist: asyncssh ~=2.18 ; extra == 'all'
@@ -20,7 +20,7 @@ ominfra/clouds/aws/journald2aws/poster.py,sha256=hz1XuctW8GtLmfjhRvCFY6py52D4BzX
20
20
  ominfra/clouds/gcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  ominfra/clouds/gcp/auth.py,sha256=3PyfRJNgajjMqJFem3SKui0CqGeHEsZlvbRhuxFcZG8,1348
22
22
  ominfra/deploy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- ominfra/deploy/_executor.py,sha256=3_ndcukzPt6Pc-5Cfnxz4OFjOYJefuTYM6ouijRjhTs,34042
23
+ ominfra/deploy/_executor.py,sha256=YnEw91L55EXvR51UTl95FtXFUe3rUmidlkD4qccE7Tg,34211
24
24
  ominfra/deploy/configs.py,sha256=qi0kwT7G2NH7dXLOQic-u6R3yeadup_QtvrjwWIggbM,435
25
25
  ominfra/deploy/remote.py,sha256=6ACmpXU1uBdyGs3Xsp97ktKFq30cJlzN9LRWNUWlGY4,2144
26
26
  ominfra/deploy/executor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
@@ -35,7 +35,7 @@ ominfra/deploy/executor/concerns/systemd.py,sha256=MtsSEToEa1HNouern_JukcYTnypw_
35
35
  ominfra/deploy/executor/concerns/user.py,sha256=j5LDfQXquIp-eEM7t6aShsrYoQrM_ILXZycTmTcRVxA,686
36
36
  ominfra/deploy/executor/concerns/venv.py,sha256=jbRriqJHO4r9Zyo5Hfl_qVmcU6Qm6UgrouBroKcPn2g,775
37
37
  ominfra/deploy/poly/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
38
- ominfra/deploy/poly/_main.py,sha256=EtMN9Cmn4plMLTXq3u_NHUUhaa8qjsyldN61AbjDQEg,24025
38
+ ominfra/deploy/poly/_main.py,sha256=iKhlTayS2j3Ra_eCSK6Qro8j4H573DLoPw8490RMIA8,24194
39
39
  ominfra/deploy/poly/base.py,sha256=Bd-CzUTaDvTRbdXKiTxMxs77WCEXItwNoBYCRnTk1u4,4167
40
40
  ominfra/deploy/poly/configs.py,sha256=9bzWdbxhOk_Q4KokDjmRz254KHnUU71Vl1frLlhQyU4,584
41
41
  ominfra/deploy/poly/deploy.py,sha256=tMYKslXLjstcv86siRt5j37USsS0Wd6lsfeGRE26zio,544
@@ -47,40 +47,42 @@ ominfra/deploy/poly/site.py,sha256=QJwDDJoVm2-kxi4bxIrp-mn4y2qDLuW3CAUax3W8gv8,2
47
47
  ominfra/deploy/poly/supervisor.py,sha256=zkl6VQBcAZaMAhyR9DbbbqULcgFCDZoe9S_vP-mMFQ8,2289
48
48
  ominfra/deploy/poly/venv.py,sha256=BoipDEa4NTeodjf3L57KJfq9eGKLagFNKwD8pS4yrzA,1552
49
49
  ominfra/journald/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ ominfra/journald/fields.py,sha256=NjjVn7GW4jkcGdyiiizVjEfQqSFnolXYk3kDcSQcMmc,12278
50
51
  ominfra/journald/genmessages.py,sha256=rLTS-K2v7otNOtTz4RoOEVYCm0fQuuBzf47e0T61tA8,1857
51
52
  ominfra/journald/messages.py,sha256=2iMY4k63XGNcN3LPvBmmK55ftjupnNh8f_ijlW9mkhQ,2208
52
- ominfra/journald/tailer.py,sha256=-CTQPkDQUBJJOpQCueFDsF5VmlfPSaSrbrGB505SUuM,36819
53
+ ominfra/journald/tailer.py,sha256=5abcFMfgi7fnY9ZEQe2ZVobaJxjQkeu6d9Kagw33a1w,33525
53
54
  ominfra/manage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
55
  ominfra/manage/manage.py,sha256=BttL8LFEknHZE_h2Pt5dAqbfUkv6qy43WI0raXBZ1a8,151
55
56
  ominfra/pyremote/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- ominfra/pyremote/_runcommands.py,sha256=IGFDDcmXJDmhGv7AFAAjkCJc615YQGUsNvn5vTAYReY,27878
57
+ ominfra/pyremote/_runcommands.py,sha256=XWBVKBE6QOlzue9lu5_wFdySt_pJ1sOj7N9KTjawW-A,28047
57
58
  ominfra/pyremote/bootstrap.py,sha256=RvMO3YGaN1E4sgUi1JEtiPak8cjvqtc_vRCq1yqbeZg,3370
58
59
  ominfra/pyremote/runcommands.py,sha256=bviS0_TDIoZVAe4h-_iavbvJtVSFu8lnk7fQ5iasCWE,1571
59
60
  ominfra/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
- ominfra/scripts/journald2aws.py,sha256=ZI6SppxsDEwnjk0zaBmAmhyi3-3VVbWubDkeGz_DEU8,98035
61
- ominfra/scripts/supervisor.py,sha256=Qf6WKD_4EkC_5QWimApONAAs3lvcAKK2X7nOaYDex48,116162
61
+ ominfra/scripts/journald2aws.py,sha256=0HHYi_uBV1t2KefVrExs3IZ6Zy-mQa7xN_ka9W9Obb8,94910
62
+ ominfra/scripts/supervisor.py,sha256=C1eT7pIqPRJgN4U87tOjR_SuOSUwd5aUswvPeTy5Xlw,121831
62
63
  ominfra/supervisor/__init__.py,sha256=Y3l4WY4JRi2uLG6kgbGp93fuGfkxkKwZDvhsa0Rwgtk,15
63
- ominfra/supervisor/__main__.py,sha256=usW9jjq5JPe_2SL8H5PrjDdksO75MX85Ir0HFfb35eM,72
64
+ ominfra/supervisor/__main__.py,sha256=I0yFw-C08OOiZ3BF6lF1Oiv789EQXu-_j6whDhQUTEA,66
64
65
  ominfra/supervisor/compat.py,sha256=Y1d_pk4eN18AbVYjDHAXMMnPwOKTFpc7JDb1uClYMsQ,5064
65
66
  ominfra/supervisor/configs.py,sha256=KpibZJ-V-4UpoJM2fnjXOXJLvDbwRJzNLXLGESUljV4,2966
66
- ominfra/supervisor/context.py,sha256=D2TCMX_P6M98_3JR2sgO97bsXEpP8EK_LTmYWgsUXqY,15337
67
+ ominfra/supervisor/context.py,sha256=Fg_wD6oUR8vxe3JMM14mR-5ssIrTNwxRr-AXfoGbzJQ,15795
67
68
  ominfra/supervisor/datatypes.py,sha256=UnXO_UlCyJD9u0uvea1wvnk_UZCzxNMeFvPK83gv530,4432
68
- ominfra/supervisor/dispatchers.py,sha256=FEZeHmrIyM6WWojJsp0wQcGacgAUpMrtHNfWVoC6vhs,10404
69
- ominfra/supervisor/events.py,sha256=OGGCuf1RWobFPDecksHJO3I4GmzBPgFvPce4-DOaZ3s,7729
69
+ ominfra/supervisor/dispatchers.py,sha256=sJ61yTo9EEbxHwe2NbzOTAFFFCuuyIhYli_xJioQBoo,10423
70
+ ominfra/supervisor/events.py,sha256=IhdL7Fj-hEvTvZ5WF6aIa2YjSPQhuUoasoJSMmRLQkU,7650
70
71
  ominfra/supervisor/exceptions.py,sha256=Qbu211H3CLlSmi9LsSikOwrcL5HgJP9ugvcKWlGTAoI,750
71
- ominfra/supervisor/poller.py,sha256=RwVnjEl63-mNQUsJcVEEsFrwuh5aOKr9e-rrB2lWCgs,7726
72
- ominfra/supervisor/process.py,sha256=RlwlHjHy8CPPMqTn1ljk2uHX628SCGwVEDfvnN22KgA,31390
72
+ ominfra/supervisor/main.py,sha256=0bj_9AzIfDlB1BB8zcX9npQIknamN7FGoVEYgLMLuP0,1701
73
+ ominfra/supervisor/poller.py,sha256=VCBxLItfA4Vj69jet2XFbFScPbmdD9JA1evaofk_AnY,7709
74
+ ominfra/supervisor/process.py,sha256=94cglin7qBwxTNXjOBxqec4qsACu-VfeboW-JfzvvbE,31454
73
75
  ominfra/supervisor/states.py,sha256=JMxXYTZhJkMNQZ2tTV6wId7wrvnWgiZteskACprKskM,1374
74
- ominfra/supervisor/supervisor.py,sha256=eXmVKX-A3exX8yHmmJEhHVd-3VnjTtrfDCvV7EEb7o8,13238
76
+ ominfra/supervisor/supervisor.py,sha256=p612yph5aKzkVLH6CfOMcRHEbNfs_TMlmjfLwtG8Jo0,12324
75
77
  ominfra/supervisor/types.py,sha256=ec62QG0CDJc0XNxCnf3lXxhsxrr4CCScLPI-1SpQjlc,1141
76
78
  ominfra/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
79
  ominfra/tailscale/api.py,sha256=C5-t_b6jZXUWcy5k8bXm7CFnk73pSdrlMOgGDeGVrpw,1370
78
80
  ominfra/tailscale/cli.py,sha256=DSGp4hn5xwOW-l_u_InKlSF6kIobxtUtVssf_73STs0,3567
79
81
  ominfra/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
82
  ominfra/tools/listresources.py,sha256=4qVg5txsb10EHhvqXXeM6gJ2jx9LbroEnPydDv1uXs0,6176
81
- ominfra-0.0.0.dev118.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
82
- ominfra-0.0.0.dev118.dist-info/METADATA,sha256=1vaiRtsilENF8WHnikugHKKzYSu2PrDx1brtN-gcG8M,742
83
- ominfra-0.0.0.dev118.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
84
- ominfra-0.0.0.dev118.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
85
- ominfra-0.0.0.dev118.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
86
- ominfra-0.0.0.dev118.dist-info/RECORD,,
83
+ ominfra-0.0.0.dev120.dist-info/LICENSE,sha256=B_hVtavaA8zCYDW99DYdcpDLKz1n3BBRjZrcbv8uG8c,1451
84
+ ominfra-0.0.0.dev120.dist-info/METADATA,sha256=xuFwZN7LnvBCDHvhqgdKONRKkDYUYJ6SZqTjaE4k2rI,742
85
+ ominfra-0.0.0.dev120.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
86
+ ominfra-0.0.0.dev120.dist-info/entry_points.txt,sha256=kgecQ2MgGrM9qK744BoKS3tMesaC3yjLnl9pa5CRczg,37
87
+ ominfra-0.0.0.dev120.dist-info/top_level.txt,sha256=E-b2OHkk_AOBLXHYZQ2EOFKl-_6uOGd8EjeG-Zy6h_w,8
88
+ ominfra-0.0.0.dev120.dist-info/RECORD,,