Science Score: 13.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
○CITATION.cff file
-
✓codemeta.json file
Found codemeta.json file -
○.zenodo.json file
-
○DOI references
-
○Academic publication links
-
○Committers with academic emails
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (10.1%) to scientific vocabulary
Repository
Service manager for asyncio
Basic Info
- Host: GitHub
- Owner: pohmelie
- License: mit
- Language: Python
- Default Branch: master
- Size: 58.6 KB
Statistics
- Stars: 17
- Watchers: 1
- Forks: 1
- Open Issues: 0
- Releases: 0
Metadata Files
readme.md
Facet
Service manager for asyncio (and classic blocking code since version 0.10.0).
Reasons
Asyncio
mode tries to do too much job:
- Messy callbacks (on_start, on_started, on_crashed, etc.).
- Inheritance restrict naming and forces super() calls.
- Forced logging module and logging configuration.
Blocking code
ExitStackis too low-level to manage services.- Common api for async and blocking worlds.
Features
- Simple (
start,stop,dependenciesandadd_task). - Configurable via inheritance (graceful shutdown timeout).
- Mixin (no
super()required). - Requires no runner engine (
Worker,Runner, etc.) just plainawaitorasync with/with.
License
facet is offered under MIT license.
Requirements
- python 3.11+
Last version with python 3.6+ support is 0.9.1
Usage
Asyncio
``` python import asyncio from facet import AsyncioServiceMixin
class B(AsyncioServiceMixin): def init(self): self.value = 0
async def start(self):
self.value += 1
print("b started")
async def stop(self):
self.value -= 1
print("b stopped")
class A(AsyncioServiceMixin): def init(self): self.b = B()
@property
def dependencies(self):
return [self.b]
async def start(self):
print("a started")
async def stop(self):
print("a stopped")
asyncio.run(A().run())
This will produce:
b started
a started
``
Start and stop order determined by strict rule: **dependencies must be started first and stopped last**. That is whyBstarts beforeA. SinceAmay useBinstart` routine.
Hit ctrl-c and you will see:
a stopped
b stopped
Traceback (most recent call last):
...
KeyboardInterrupt
Stop order is reversed, since A may use B in stop routine. Any raised exception propagates to upper context. facet do not trying to be too smart.
Service can be used as a context manager. Instead of
python
asyncio.run(A().run())
Code can look like:
``` python
async def main():
async with A() as a:
assert a.b.value == 1
await a.wait()
asyncio.run(main()) ```
Another service feature is add_task method:
``` python
class A(AsyncioServiceMixin):
async def task(self):
await asyncio.sleep(1)
print("task done")
async def start(self):
self.add_task(self.task())
print("start done")
asyncio.run(A().run())
This will lead to background task creation and handling:
start done
task done
```
Any non-handled exception on background task will lead the whole service stack crashed. This is also a key feature to fall down fast and loud.
All background tasks will be cancelled and awaited on service stop.
You can manage dependencies start/stop to start sequently, parallel or mixed. Like this: ``` python class A(AsyncioServiceMixin): def init(self): self.b = B() self.c = C() self.d = D()
@property
def dependencies(self):
return [
[self.b, self.c],
self.d,
]
``
This leads to firstbandcstarts parallel, after they successfully starteddwill try to start, and thenaitself start will be called. And on stop routineastop called first, thendstop, then bothbandc` stops parallel.
The rule here is first nesting level is sequential, second nesting level is parallel
Blocking code
Since version 0.10.0 facet can be used in blocking code with pretty same rules. But with limited API. For example:
``` python
from facet import BlockingServiceMixin
class B(BlockingServiceMixin): def init(self): self.value = 0
def start(self):
self.value += 1
print("b started")
def stop(self):
self.value -= 1
print("b stopped")
class A(BlockingServiceMixin): def init(self): self.b = B()
@property
def dependencies(self):
return [self.b]
def start(self):
print("a started")
def stop(self):
print("a stopped")
with A() as a:
assert a.b.value == 1
This will produce:
b started
a started
a stopped
b stopped
``
As you can see, there is nowaitmethod. Waiting and background tasks are on user shoulders and technically can be implemented withconcurrent.futuresmodule. Butfacetdo not provide such functionality, since there are a lot of ways to do it:threading/multiprocessing` and their primitives.
Also, there are no «sequential, parallel and mixed starts/stops for dependencies» feature. So, just put dependencies in dependencies property as a plain list and they will be started/stopped sequentially.
API
Asyncio
Here is public methods you get on inheritance/mixin:
start
python
async def start(self):
pass
Start routine.
stop
python
async def stop(self):
pass
Stop routine.
dependencies
python
@property
def dependencies(self) -> list[AsyncioServiceMixin | list[AsyncioServiceMixin]]:
return []
Should return iterable of current service dependencies instances.
add_task
python
def add_task(self, coroutine: Coroutine[Any, Any, Any]) -> asyncio.Task[Any]:
Add background task.
run
python
async def run(self) -> None:
Run service and wait until it stop.
wait
python
async def wait(self) -> None:
Wait for service stop. Service must be started. This is useful when you use service as a context manager.
graceful_shutdown_timeout
python
@property
def graceful_shutdown_timeout(self) -> int:
return 10
How much total time in seconds wait for stop routines. This property can be overriden with subclass:
python
class CustomServiceMixin(AsyncioServiceMixin):
@property
def graceful_shutdown_timeout(self):
return 60
running
python
@property
def running(self) -> bool:
Check if service is running
Blocking code
start
python
def start(self):
pass
Start routine.
stop
python
def stop(self):
pass
Stop routine.
dependencies
python
@property
def dependencies(self) -> list[BlockingServiceMixin | list[BlockingServiceMixin]]:
return []
Should return iterable of current service dependencies instances.
running
python
@property
def running(self) -> bool:
Check if service is running
Owner
- Name: Nikita Melentev
- Login: pohmelie
- Kind: user
- Location: Tbilisi, Georgia
- Repositories: 89
- Profile: https://github.com/pohmelie
GitHub Events
Total
- Watch event: 4
Last Year
- Watch event: 4
Committers
Last synced: almost 3 years ago
Top Committers
| Name | Commits | |
|---|---|---|
| pohmelie | m****y@g****m | 20 |
| Nikita Melentev | n****v@k****u | 7 |
| Sergey | b****z@g****m | 4 |
| Nikita Melentev | N****v@k****u | 1 |
Committer Domains (Top 20 + Academic)
Issues and Pull Requests
Last synced: about 1 year ago
All Time
- Total issues: 3
- Total pull requests: 4
- Average time to close issues: about 1 month
- Average time to close pull requests: 3 days
- Total issue authors: 2
- Total pull request authors: 1
- Average comments per issue: 3.33
- Average comments per pull request: 2.0
- Merged pull requests: 4
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 0
- Pull requests: 0
- Average time to close issues: N/A
- Average time to close pull requests: N/A
- Issue authors: 0
- Pull request authors: 0
- Average comments per issue: 0
- Average comments per pull request: 0
- Merged pull requests: 0
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- pohmelie (2)
- Vasiliy566 (1)
Pull Request Authors
- bizywizy (4)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- pypi 5,071 last-month
- Total dependent packages: 1
- Total dependent repositories: 2
- Total versions: 12
- Total maintainers: 1
pypi.org: facet
service manager for asyncio
- Documentation: https://github.com/pohmelie/facet
- License: MIT License Copyright (c) 2019 Nikita Melentev Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
Latest release: 0.10.1
published over 2 years ago
Rankings
Maintainers (1)
Dependencies
- actions/checkout v2 composite
- actions/setup-python v2 composite
- casperdcl/deploy-pypi v2 composite
- codecov/codecov-action v2 composite