ominfra 0.0.0.dev123__py3-none-any.whl → 0.0.0.dev125__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,28 @@
1
+ Supervisor is licensed under the following license:
2
+
3
+ A copyright notice accompanies this license document that identifies the copyright holders.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6
+ following conditions are met:
7
+
8
+ 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the
9
+ following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the
12
+ following disclaimer in the documentation and/or other materials provided with the distribution.
13
+
14
+ 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without
15
+ prior written permission from the copyright holders.
16
+
17
+ 4. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed the
18
+ files and the date of any change.
19
+
20
+ Disclaimer
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
23
+ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
24
+ EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -20,8 +20,8 @@ from .exceptions import NotExecutableError
20
20
  from .exceptions import NotFoundError
21
21
  from .poller import Poller
22
22
  from .states import SupervisorState
23
- from .types import AbstractServerContext
24
- from .types import AbstractSubprocess
23
+ from .types import Process
24
+ from .types import ServerContext
25
25
  from .utils import close_fd
26
26
  from .utils import mktempfile
27
27
  from .utils import real_exit
@@ -31,7 +31,7 @@ from .utils import try_unlink
31
31
  ServerEpoch = ta.NewType('ServerEpoch', int)
32
32
 
33
33
 
34
- class ServerContext(AbstractServerContext):
34
+ class ServerContextImpl(ServerContext):
35
35
  def __init__(
36
36
  self,
37
37
  config: ServerConfig,
@@ -45,7 +45,7 @@ class ServerContext(AbstractServerContext):
45
45
  self._poller = poller
46
46
  self._epoch = epoch
47
47
 
48
- self._pid_history: ta.Dict[int, AbstractSubprocess] = {}
48
+ self._pid_history: ta.Dict[int, Process] = {}
49
49
  self._state: SupervisorState = SupervisorState.RUNNING
50
50
 
51
51
  if config.user is not None:
@@ -78,7 +78,7 @@ class ServerContext(AbstractServerContext):
78
78
  self._state = state
79
79
 
80
80
  @property
81
- def pid_history(self) -> ta.Dict[int, AbstractSubprocess]:
81
+ def pid_history(self) -> ta.Dict[int, Process]:
82
82
  return self._pid_history
83
83
 
84
84
  @property
@@ -12,7 +12,7 @@ from .events import EventCallbacks
12
12
  from .events import ProcessCommunicationEvent
13
13
  from .events import ProcessLogStderrEvent
14
14
  from .events import ProcessLogStdoutEvent
15
- from .types import AbstractSubprocess
15
+ from .types import Process
16
16
  from .utils import as_bytes
17
17
  from .utils import compact_traceback
18
18
  from .utils import find_prefix_at_end
@@ -23,7 +23,7 @@ from .utils import strip_escapes
23
23
  class Dispatcher(abc.ABC):
24
24
  def __init__(
25
25
  self,
26
- process: AbstractSubprocess,
26
+ process: Process,
27
27
  channel: str,
28
28
  fd: int,
29
29
  *,
@@ -42,7 +42,7 @@ class Dispatcher(abc.ABC):
42
42
  return f'<{self.__class__.__name__} at {id(self)} for {self._process} ({self._channel})>'
43
43
 
44
44
  @property
45
- def process(self) -> AbstractSubprocess:
45
+ def process(self) -> Process:
46
46
  return self._process
47
47
 
48
48
  @property
@@ -97,7 +97,7 @@ class OutputDispatcher(Dispatcher):
97
97
 
98
98
  def __init__(
99
99
  self,
100
- process: AbstractSubprocess,
100
+ process: Process,
101
101
  event_type: ta.Type[ProcessCommunicationEvent],
102
102
  fd: int,
103
103
  **kwargs: ta.Any,
@@ -306,7 +306,7 @@ class OutputDispatcher(Dispatcher):
306
306
  class InputDispatcher(Dispatcher):
307
307
  def __init__(
308
308
  self,
309
- process: AbstractSubprocess,
309
+ process: Process,
310
310
  channel: str,
311
311
  fd: int,
312
312
  **kwargs: ta.Any,
@@ -5,6 +5,9 @@ import typing as ta
5
5
  from .states import ProcessState
6
6
 
7
7
 
8
+ EventCallback = ta.Callable[['Event'], None]
9
+
10
+
8
11
  ##
9
12
 
10
13
 
@@ -15,9 +18,6 @@ class Event(abc.ABC): # noqa
15
18
  ##
16
19
 
17
20
 
18
- EventCallback = ta.Callable[['Event'], None]
19
-
20
-
21
21
  class EventCallbacks:
22
22
  def __init__(self) -> None:
23
23
  super().__init__()
@@ -1,48 +1,42 @@
1
1
  # ruff: noqa: UP006 UP007
2
- import dataclasses as dc
3
2
  import typing as ta
4
3
 
5
- from .configs import ProcessConfig
4
+ from omlish.lite.typing import Func
5
+
6
6
  from .configs import ProcessGroupConfig
7
- from .context import ServerContext
8
7
  from .dispatchers import Dispatcher
9
8
  from .events import EventCallbacks
10
9
  from .events import ProcessGroupAddedEvent
11
10
  from .events import ProcessGroupRemovedEvent
12
11
  from .states import ProcessState
13
- from .types import AbstractProcessGroup
14
- from .types import AbstractServerContext
15
- from .types import AbstractSubprocess
12
+ from .types import Process
13
+ from .types import ProcessGroup
14
+ from .types import ServerContext
16
15
 
17
16
 
18
17
  ##
19
18
 
20
19
 
21
- @dc.dataclass(frozen=True)
22
- class SubprocessFactory:
23
- fn: ta.Callable[[ProcessConfig, AbstractProcessGroup], AbstractSubprocess]
24
-
25
- def __call__(self, config: ProcessConfig, group: AbstractProcessGroup) -> AbstractSubprocess:
26
- return self.fn(config, group)
20
+ ProcessFactory = ta.NewType('ProcessFactory', Func[Process]) # (config: ProcessConfig, group: ProcessGroup)
27
21
 
28
22
 
29
- class ProcessGroup(AbstractProcessGroup):
23
+ class ProcessGroupImpl(ProcessGroup):
30
24
  def __init__(
31
25
  self,
32
26
  config: ProcessGroupConfig,
33
27
  context: ServerContext,
34
28
  *,
35
- subprocess_factory: SubprocessFactory,
29
+ process_factory: ProcessFactory,
36
30
  ):
37
31
  super().__init__()
38
32
 
39
33
  self._config = config
40
34
  self._context = context
41
- self._subprocess_factory = subprocess_factory
35
+ self._process_factory = process_factory
42
36
 
43
37
  self._processes = {}
44
38
  for pconfig in self._config.processes or []:
45
- process = self._subprocess_factory(pconfig, self)
39
+ process = self._process_factory(pconfig, self)
46
40
  self._processes[pconfig.name] = process
47
41
 
48
42
  @property
@@ -54,7 +48,7 @@ class ProcessGroup(AbstractProcessGroup):
54
48
  return self._config.name
55
49
 
56
50
  @property
57
- def context(self) -> AbstractServerContext:
51
+ def context(self) -> ServerContext:
58
52
  return self._context
59
53
 
60
54
  def __repr__(self):
@@ -89,7 +83,7 @@ class ProcessGroup(AbstractProcessGroup):
89
83
  # BACKOFF -> FATAL
90
84
  proc.give_up()
91
85
 
92
- def get_unstopped_processes(self) -> ta.List[AbstractSubprocess]:
86
+ def get_unstopped_processes(self) -> ta.List[Process]:
93
87
  return [x for x in self._processes.values() if not x.get_state().stopped]
94
88
 
95
89
  def get_dispatchers(self) -> ta.Dict[int, Dispatcher]:
@@ -0,0 +1,64 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import typing as ta
3
+
4
+ from omlish.lite.inject import InjectorBindingOrBindings
5
+ from omlish.lite.inject import InjectorBindings
6
+ from omlish.lite.inject import inj
7
+
8
+ from .configs import ServerConfig
9
+ from .context import ServerContextImpl
10
+ from .context import ServerEpoch
11
+ from .events import EventCallbacks
12
+ from .groups import ProcessFactory
13
+ from .groups import ProcessGroupImpl
14
+ from .poller import Poller
15
+ from .poller import get_poller_impl
16
+ from .process import InheritedFds
17
+ from .process import ProcessImpl
18
+ from .signals import SignalReceiver
19
+ from .supervisor import ProcessGroupFactory
20
+ from .supervisor import ProcessGroups
21
+ from .supervisor import SignalHandler
22
+ from .supervisor import Supervisor
23
+ from .types import ServerContext
24
+
25
+
26
+ ##
27
+
28
+
29
+ def bind_server(
30
+ config: ServerConfig,
31
+ *,
32
+ server_epoch: ta.Optional[ServerEpoch] = None,
33
+ inherited_fds: ta.Optional[InheritedFds] = None,
34
+ ) -> InjectorBindings:
35
+ lst: ta.List[InjectorBindingOrBindings] = [
36
+ inj.bind(config),
37
+
38
+ inj.bind(get_poller_impl(), key=Poller, singleton=True),
39
+
40
+ inj.bind(ServerContextImpl, singleton=True),
41
+ inj.bind(ServerContext, to_key=ServerContextImpl),
42
+
43
+ inj.bind(EventCallbacks, singleton=True),
44
+
45
+ inj.bind(SignalReceiver, singleton=True),
46
+
47
+ inj.bind(SignalHandler, singleton=True),
48
+ inj.bind(ProcessGroups, singleton=True),
49
+ inj.bind(Supervisor, singleton=True),
50
+
51
+ inj.bind_factory(ProcessGroupFactory, ProcessGroupImpl),
52
+ inj.bind_factory(ProcessFactory, ProcessImpl),
53
+ ]
54
+
55
+ #
56
+
57
+ if server_epoch is not None:
58
+ lst.append(inj.bind(server_epoch, key=ServerEpoch))
59
+ if inherited_fds is not None:
60
+ lst.append(inj.bind(inherited_fds, key=InheritedFds))
61
+
62
+ #
63
+
64
+ return inj.as_bindings(*lst)
@@ -1,41 +1,52 @@
1
1
  #!/usr/bin/env python3
2
2
  # ruff: noqa: UP006 UP007
3
3
  # @omlish-amalg ../scripts/supervisor.py
4
- import functools
4
+ # Supervisor is licensed under the following license:
5
+ #
6
+ # A copyright notice accompanies this license document that identifies the copyright holders.
7
+ #
8
+ # Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
9
+ # following conditions are met:
10
+ #
11
+ # 1. Redistributions in source code must retain the accompanying copyright notice, this list of conditions, and the
12
+ # following disclaimer.
13
+ #
14
+ # 2. Redistributions in binary form must reproduce the accompanying copyright notice, this list of conditions, and the
15
+ # following disclaimer in the documentation and/or other materials provided with the distribution.
16
+ #
17
+ # 3. Names of the copyright holders must not be used to endorse or promote products derived from this software without
18
+ # prior written permission from the copyright holders.
19
+ #
20
+ # 4. If any files are modified, you must cause the modified files to carry prominent notices stating that you changed
21
+ # the files and the date of any change.
22
+ #
23
+ # Disclaimer
24
+ #
25
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
26
+ # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
27
+ # EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5
32
  import itertools
6
33
  import os.path
7
34
  import typing as ta
8
35
 
9
- from omlish.lite.inject import Injector
10
- from omlish.lite.inject import InjectorBindingOrBindings
11
- from omlish.lite.inject import InjectorBindings
36
+ from omlish.lite.http.coroserver import CoroHttpServer
12
37
  from omlish.lite.inject import inj
13
38
  from omlish.lite.journald import journald_log_handler_factory
14
39
  from omlish.lite.logs import configure_standard_logging
15
40
 
16
41
  from ..configs import read_config_file
17
- from .configs import ProcessConfig
18
- from .configs import ProcessGroupConfig
19
42
  from .configs import ServerConfig
20
43
  from .configs import prepare_server_config
21
- from .context import ServerContext
44
+ from .context import ServerContextImpl
22
45
  from .context import ServerEpoch
23
- from .events import EventCallbacks
24
- from .groups import ProcessGroup
25
- from .groups import SubprocessFactory
26
- from .poller import Poller
27
- from .poller import get_poller_impl
46
+ from .inject import bind_server
28
47
  from .process import InheritedFds
29
- from .process import Subprocess
30
- from .signals import SignalReceiver
31
48
  from .states import SupervisorState
32
- from .supervisor import ProcessGroupFactory
33
- from .supervisor import ProcessGroups
34
- from .supervisor import SignalHandler
35
49
  from .supervisor import Supervisor
36
- from .types import AbstractProcessGroup
37
- from .types import AbstractServerContext
38
- from .types import AbstractSubprocess
39
50
  from .utils import ExitNow
40
51
  from .utils import get_open_fds
41
52
 
@@ -43,63 +54,15 @@ from .utils import get_open_fds
43
54
  ##
44
55
 
45
56
 
46
- def build_server_bindings(
47
- config: ServerConfig,
48
- *,
49
- server_epoch: ta.Optional[ServerEpoch] = None,
50
- inherited_fds: ta.Optional[InheritedFds] = None,
51
- ) -> InjectorBindings:
52
- lst: ta.List[InjectorBindingOrBindings] = [
53
- inj.bind(config),
54
-
55
- inj.bind(get_poller_impl(), key=Poller, singleton=True),
56
-
57
- inj.bind(ServerContext, singleton=True),
58
- inj.bind(AbstractServerContext, to_key=ServerContext),
59
-
60
- inj.bind(EventCallbacks, singleton=True),
61
-
62
- inj.bind(SignalReceiver, singleton=True),
63
-
64
- inj.bind(SignalHandler, singleton=True),
65
- inj.bind(ProcessGroups, singleton=True),
66
- inj.bind(Supervisor, singleton=True),
67
- ]
68
-
69
- #
70
-
71
- def make_process_group_factory(injector: Injector) -> ProcessGroupFactory:
72
- def inner(group_config: ProcessGroupConfig) -> ProcessGroup:
73
- return injector.inject(functools.partial(ProcessGroup, group_config))
74
- return ProcessGroupFactory(inner)
75
- lst.append(inj.bind(make_process_group_factory))
76
-
77
- def make_subprocess_factory(injector: Injector) -> SubprocessFactory:
78
- def inner(process_config: ProcessConfig, group: AbstractProcessGroup) -> AbstractSubprocess:
79
- return injector.inject(functools.partial(Subprocess, process_config, group))
80
- return SubprocessFactory(inner)
81
- lst.append(inj.bind(make_subprocess_factory))
82
-
83
- #
84
-
85
- if server_epoch is not None:
86
- lst.append(inj.bind(server_epoch, key=ServerEpoch))
87
- if inherited_fds is not None:
88
- lst.append(inj.bind(inherited_fds, key=InheritedFds))
89
-
90
- #
91
-
92
- return inj.as_bindings(*lst)
93
-
94
-
95
- ##
96
-
97
-
98
57
  def main(
99
58
  argv: ta.Optional[ta.Sequence[str]] = None,
100
59
  *,
101
60
  no_logging: bool = False,
102
61
  ) -> None:
62
+ server_cls = CoroHttpServer # noqa
63
+
64
+ #
65
+
103
66
  import argparse
104
67
 
105
68
  parser = argparse.ArgumentParser()
@@ -133,14 +96,14 @@ def main(
133
96
  prepare=prepare_server_config,
134
97
  )
135
98
 
136
- injector = inj.create_injector(build_server_bindings(
99
+ injector = inj.create_injector(bind_server(
137
100
  config,
138
101
  server_epoch=ServerEpoch(epoch),
139
102
  inherited_fds=inherited_fds,
140
103
  ))
141
104
 
142
- context = injector.provide(ServerContext)
143
- supervisor = injector.provide(Supervisor)
105
+ context = injector[ServerContextImpl]
106
+ supervisor = injector[Supervisor]
144
107
 
145
108
  try:
146
109
  supervisor.main()
@@ -30,9 +30,9 @@ from .exceptions import ProcessError
30
30
  from .signals import sig_name
31
31
  from .states import ProcessState
32
32
  from .states import SupervisorState
33
- from .types import AbstractProcessGroup
34
- from .types import AbstractServerContext
35
- from .types import AbstractSubprocess
33
+ from .types import Process
34
+ from .types import ProcessGroup
35
+ from .types import ServerContext
36
36
  from .utils import as_bytes
37
37
  from .utils import as_string
38
38
  from .utils import close_fd
@@ -48,15 +48,15 @@ InheritedFds = ta.NewType('InheritedFds', ta.FrozenSet[int])
48
48
  ##
49
49
 
50
50
 
51
- class Subprocess(AbstractSubprocess):
51
+ class ProcessImpl(Process):
52
52
  """A class to manage a subprocess."""
53
53
 
54
54
  def __init__(
55
55
  self,
56
56
  config: ProcessConfig,
57
- group: AbstractProcessGroup,
57
+ group: ProcessGroup,
58
58
  *,
59
- context: AbstractServerContext,
59
+ context: ServerContext,
60
60
  event_callbacks: EventCallbacks,
61
61
 
62
62
  inherited_fds: ta.Optional[InheritedFds] = None,
@@ -95,7 +95,7 @@ class Subprocess(AbstractSubprocess):
95
95
  return self._pid
96
96
 
97
97
  @property
98
- def group(self) -> AbstractProcessGroup:
98
+ def group(self) -> ProcessGroup:
99
99
  return self._group
100
100
 
101
101
  @property
@@ -103,7 +103,7 @@ class Subprocess(AbstractSubprocess):
103
103
  return self._config
104
104
 
105
105
  @property
106
- def context(self) -> AbstractServerContext:
106
+ def context(self) -> ServerContext:
107
107
  return self._context
108
108
 
109
109
  @property
@@ -1,5 +1,4 @@
1
1
  # ruff: noqa: UP006 UP007
2
- import dataclasses as dc
3
2
  import signal
4
3
  import time
5
4
  import typing as ta
@@ -7,9 +6,10 @@ import typing as ta
7
6
  from omlish.lite.cached import cached_nullary
8
7
  from omlish.lite.check import check_not_none
9
8
  from omlish.lite.logs import log
9
+ from omlish.lite.typing import Func
10
10
 
11
11
  from .configs import ProcessGroupConfig
12
- from .context import ServerContext
12
+ from .context import ServerContextImpl
13
13
  from .dispatchers import Dispatcher
14
14
  from .events import TICK_EVENTS
15
15
  from .events import EventCallbacks
@@ -18,10 +18,10 @@ from .events import SupervisorStoppingEvent
18
18
  from .groups import ProcessGroup
19
19
  from .groups import ProcessGroups
20
20
  from .poller import Poller
21
- from .process import Subprocess
22
21
  from .signals import SignalReceiver
23
22
  from .signals import sig_name
24
23
  from .states import SupervisorState
24
+ from .types import Process
25
25
  from .utils import ExitNow
26
26
  from .utils import as_string
27
27
  from .utils import decode_wait_status
@@ -35,7 +35,7 @@ class SignalHandler:
35
35
  def __init__(
36
36
  self,
37
37
  *,
38
- context: ServerContext,
38
+ context: ServerContextImpl,
39
39
  signal_receiver: SignalReceiver,
40
40
  process_groups: ProcessGroups,
41
41
  ) -> None:
@@ -87,19 +87,14 @@ class SignalHandler:
87
87
  ##
88
88
 
89
89
 
90
- @dc.dataclass(frozen=True)
91
- class ProcessGroupFactory:
92
- fn: ta.Callable[[ProcessGroupConfig], ProcessGroup]
93
-
94
- def __call__(self, config: ProcessGroupConfig) -> ProcessGroup:
95
- return self.fn(config)
90
+ ProcessGroupFactory = ta.NewType('ProcessGroupFactory', Func[ProcessGroup]) # (config: ProcessGroupConfig)
96
91
 
97
92
 
98
93
  class Supervisor:
99
94
  def __init__(
100
95
  self,
101
96
  *,
102
- context: ServerContext,
97
+ context: ServerContextImpl,
103
98
  poller: Poller,
104
99
  process_groups: ProcessGroups,
105
100
  signal_handler: SignalHandler,
@@ -123,7 +118,7 @@ class Supervisor:
123
118
  #
124
119
 
125
120
  @property
126
- def context(self) -> ServerContext:
121
+ def context(self) -> ServerContextImpl:
127
122
  return self._context
128
123
 
129
124
  def get_state(self) -> SupervisorState:
@@ -170,16 +165,16 @@ class Supervisor:
170
165
  return True
171
166
 
172
167
  def get_process_map(self) -> ta.Dict[int, Dispatcher]:
173
- process_map = {}
168
+ process_map: ta.Dict[int, Dispatcher] = {}
174
169
  for group in self._process_groups:
175
170
  process_map.update(group.get_dispatchers())
176
171
  return process_map
177
172
 
178
- def shutdown_report(self) -> ta.List[Subprocess]:
179
- unstopped: ta.List[Subprocess] = []
173
+ def shutdown_report(self) -> ta.List[Process]:
174
+ unstopped: ta.List[Process] = []
180
175
 
181
176
  for group in self._process_groups:
182
- unstopped.extend(group.get_unstopped_processes()) # type: ignore
177
+ unstopped.extend(group.get_unstopped_processes())
183
178
 
184
179
  if unstopped:
185
180
  # throttle 'waiting for x to die' reports
@@ -10,7 +10,7 @@ from .states import ProcessState
10
10
  from .states import SupervisorState
11
11
 
12
12
 
13
- class AbstractServerContext(abc.ABC):
13
+ class ServerContext(abc.ABC):
14
14
  @property
15
15
  @abc.abstractmethod
16
16
  def config(self) -> ServerConfig:
@@ -27,12 +27,24 @@ class AbstractServerContext(abc.ABC):
27
27
 
28
28
  @property
29
29
  @abc.abstractmethod
30
- def pid_history(self) -> ta.Dict[int, 'AbstractSubprocess']:
30
+ def pid_history(self) -> ta.Dict[int, 'Process']:
31
31
  raise NotImplementedError
32
32
 
33
33
 
34
+ # class Dispatcher(abc.ABC):
35
+ # pass
36
+ #
37
+ #
38
+ # class OutputDispatcher(Dispatcher, abc.ABC):
39
+ # pass
40
+ #
41
+ #
42
+ # class InputDispatcher(Dispatcher, abc.ABC):
43
+ # pass
44
+
45
+
34
46
  @functools.total_ordering
35
- class AbstractSubprocess(abc.ABC):
47
+ class Process(abc.ABC):
36
48
  @property
37
49
  @abc.abstractmethod
38
50
  def pid(self) -> int:
@@ -51,7 +63,7 @@ class AbstractSubprocess(abc.ABC):
51
63
 
52
64
  @property
53
65
  @abc.abstractmethod
54
- def context(self) -> AbstractServerContext:
66
+ def context(self) -> ServerContext:
55
67
  raise NotImplementedError
56
68
 
57
69
  @abc.abstractmethod
@@ -87,12 +99,12 @@ class AbstractSubprocess(abc.ABC):
87
99
  raise NotImplementedError
88
100
 
89
101
  @abc.abstractmethod
90
- def get_dispatchers(self) -> ta.Mapping[int, ta.Any]: # dict[int, Dispatcher]
102
+ def get_dispatchers(self) -> ta.Mapping[int, ta.Any]: # Dispatcher]:
91
103
  raise NotImplementedError
92
104
 
93
105
 
94
106
  @functools.total_ordering
95
- class AbstractProcessGroup(abc.ABC):
107
+ class ProcessGroup(abc.ABC):
96
108
  @property
97
109
  @abc.abstractmethod
98
110
  def config(self) -> ProcessGroupConfig:
@@ -103,3 +115,36 @@ class AbstractProcessGroup(abc.ABC):
103
115
 
104
116
  def __eq__(self, other):
105
117
  return self.config.priority == other.config.priority
118
+
119
+ @abc.abstractmethod
120
+ def transition(self) -> None:
121
+ raise NotImplementedError
122
+
123
+ @abc.abstractmethod
124
+ def stop_all(self) -> None:
125
+ raise NotImplementedError
126
+
127
+ @property
128
+ @abc.abstractmethod
129
+ def name(self) -> str:
130
+ raise NotImplementedError
131
+
132
+ @abc.abstractmethod
133
+ def before_remove(self) -> None:
134
+ raise NotImplementedError
135
+
136
+ @abc.abstractmethod
137
+ def get_dispatchers(self) -> ta.Mapping[int, ta.Any]: # Dispatcher]:
138
+ raise NotImplementedError
139
+
140
+ @abc.abstractmethod
141
+ def reopen_logs(self) -> None:
142
+ raise NotImplementedError
143
+
144
+ @abc.abstractmethod
145
+ def get_unstopped_processes(self) -> ta.List[Process]:
146
+ raise NotImplementedError
147
+
148
+ @abc.abstractmethod
149
+ def after_setuid(self) -> None:
150
+ raise NotImplementedError
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ominfra
3
- Version: 0.0.0.dev123
3
+ Version: 0.0.0.dev125
4
4
  Summary: ominfra
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -12,12 +12,11 @@ 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.dev123
16
- Requires-Dist: omlish ==0.0.0.dev123
15
+ Requires-Dist: omdev==0.0.0.dev125
16
+ Requires-Dist: omlish==0.0.0.dev125
17
17
  Provides-Extra: all
18
- Requires-Dist: paramiko ~=3.5 ; extra == 'all'
19
- Requires-Dist: asyncssh ~=2.18 ; extra == 'all'
18
+ Requires-Dist: paramiko~=3.5; extra == "all"
19
+ Requires-Dist: asyncssh~=2.18; extra == "all"
20
20
  Provides-Extra: ssh
21
- Requires-Dist: paramiko ~=3.5 ; extra == 'ssh'
22
- Requires-Dist: asyncssh ~=2.18 ; extra == 'ssh'
23
-
21
+ Requires-Dist: paramiko~=3.5; extra == "ssh"
22
+ Requires-Dist: asyncssh~=2.18; extra == "ssh"