Skip to content

Commit d9a5867

Browse files
authored
Reload dependencies are now optional. (#98)
1 parent 979ffb9 commit d9a5867

File tree

7 files changed

+63
-28
lines changed

7 files changed

+63
-28
lines changed

docs/guide/cli.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,29 @@ To disable this pass the `--no-parse` option to the taskiq.
4747
### Hot reload
4848

4949
This is annoying to restart workers every time you modify tasks. That's why taskiq supports hot-reload.
50-
To enable this option simply pass the `--reload` or `-r` option to taskiq CLI.
50+
Reload is unavailable by default. To enable this feature install taskiq with `reload` extra.
5151

52-
Also this option supports `.gitignore` files. If you have such files in your directory. It won't reload worker
53-
if you ignore file's contents. To disable this functionality pass `--do-not-use-gitignore` option.
52+
::: tabs
53+
54+
55+
@tab pip
56+
57+
```bash:no-line-numbers
58+
pip install "taskiq[reload]"
59+
```
60+
61+
@tab poetry
62+
63+
```bash:no-line-numbers
64+
poetry add taskiq -E reload
65+
```
66+
67+
:::
68+
69+
To enable this option simply pass the `--reload` or `-r` option to worker taskiq CLI.
70+
71+
Also this option supports `.gitignore` files. If you have such file in your directory, it won't reload worker
72+
when you modify ignored files. To disable this functionality pass `--do-not-use-gitignore` option.
5473

5574
## Scheduler
5675

poetry.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,18 @@ keywords = ["taskiq", "tasks", "distributed", "async"]
2929
python = "^3.7"
3030
typing-extensions = ">=3.10.0.0"
3131
pydantic = "^1.6.2"
32-
pyzmq = { version = "^23.2.0", optional = true }
33-
uvloop = { version = ">=0.16.0,<1", optional = true }
34-
watchdog = "^2.1.9"
35-
gitignore-parser = "^0"
3632
importlib-metadata = "*"
3733
pycron = "^3.0.0"
3834
taskiq_dependencies = "^1"
35+
# For prometheus metrics
3936
prometheus_client = { version = "^0", optional = true }
37+
# For ZMQBroker
38+
pyzmq = { version = "^23.2.0", optional = true }
39+
# For speed
40+
uvloop = { version = ">=0.16.0,<1", optional = true }
41+
# For hot-reload.
42+
watchdog = { version = "^2.1.9", optional = true }
43+
gitignore-parser = { version = "^0", optional = true }
4044

4145
[tool.poetry.dev-dependencies]
4246
pytest = "^7.1.2"
@@ -59,6 +63,7 @@ types-mock = "^4.0.15"
5963
zmq = ["pyzmq"]
6064
uv = ["uvloop"]
6165
metrics = ["prometheus_client"]
66+
reload = ["watchdog", "gitignore-parser"]
6267

6368
[tool.poetry.scripts]
6469
taskiq = "taskiq.__main__:main"

taskiq/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ def main() -> None: # noqa: WPS210 # pragma: no cover
4646
for entrypoint in entry_points().select(group="taskiq_cli"):
4747
try:
4848
cmd_class = entrypoint.load()
49-
except ImportError:
50-
print(f"Could not load {entrypoint.value}") # noqa: WPS421
49+
except ImportError as exc:
50+
print(f"Could not load {entrypoint.value}. Cause: {exc}") # noqa: WPS421
5151
continue
5252
if issubclass(cmd_class, TaskiqCMD):
5353
subparsers.add_parser(

taskiq/cli/worker/args.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ def from_cli( # noqa: WPS213
116116
"--reload",
117117
"-r",
118118
action="store_true",
119-
help="Reload workers if file is changed.",
119+
help="Reload workers if file is changed. "
120+
+ "`reload` extra is required for this option.",
120121
)
121122
parser.add_argument(
122123
"--do-not-use-gitignore",

taskiq/cli/worker/process_manager.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33
from dataclasses import dataclass
44
from multiprocessing import Process, Queue
55
from time import sleep
6-
from typing import Any, Callable, List
6+
from typing import Any, Callable, List, Optional
77

8-
from watchdog.observers import Observer
8+
try:
9+
from watchdog.observers import Observer # noqa: WPS433
10+
11+
from taskiq.cli.watcher import FileWatcher # noqa: WPS433
12+
except ImportError:
13+
Observer = None # type: ignore
14+
FileWatcher = None # type: ignore
915

10-
from taskiq.cli.watcher import FileWatcher
1116
from taskiq.cli.worker.args import WorkerArgs
1217

1318
logger = logging.getLogger("taskiq.process-manager")
@@ -132,13 +137,13 @@ class ProcessManager:
132137
def __init__(
133138
self,
134139
args: WorkerArgs,
135-
observer: Observer,
136140
worker_function: Callable[[WorkerArgs], None],
141+
observer: Optional[Observer] = None,
137142
) -> None:
138143
self.worker_function = worker_function
139144
self.action_queue: "Queue[ProcessActionBase]" = Queue(-1)
140145
self.args = args
141-
if args.reload:
146+
if args.reload and observer is not None:
142147
observer.schedule(
143148
FileWatcher(
144149
callback=schedule_workers_reload,

taskiq/cli/worker/run.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
from concurrent.futures import ThreadPoolExecutor
55
from typing import Any
66

7-
from watchdog.observers import Observer
8-
97
from taskiq.abc.broker import AsyncBroker
108
from taskiq.cli.utils import import_object, import_tasks
119
from taskiq.cli.worker.args import WorkerArgs
@@ -18,6 +16,11 @@
1816
uvloop = None # type: ignore
1917

2018

19+
try:
20+
from watchdog.observers import Observer # noqa: WPS433
21+
except ImportError:
22+
Observer = None # type: ignore
23+
2124
logger = logging.getLogger("taskiq.worker")
2225

2326

@@ -133,9 +136,11 @@ def run_worker(args: WorkerArgs) -> None: # noqa: WPS213
133136
logging.getLogger("watchdog.observers.inotify_buffer").setLevel(level=logging.INFO)
134137
logger.info("Starting %s worker processes.", args.workers)
135138

136-
observer = Observer()
139+
observer = None
140+
if Observer is not None:
141+
observer = Observer()
137142

138-
if args.reload:
143+
if observer is not None and args.reload:
139144
observer.start()
140145
args.workers = 1
141146
logging.warning(
@@ -146,7 +151,7 @@ def run_worker(args: WorkerArgs) -> None: # noqa: WPS213
146151

147152
manager.start()
148153

149-
if observer.is_alive():
154+
if observer is not None and observer.is_alive():
150155
if args.reload:
151156
logger.info("Stopping watching files.")
152157
observer.stop()

0 commit comments

Comments
 (0)