Classwork
This is a simple Python module to help distribute you tasks across multiple brokers as microservices.
Classwork uses NATS to manage communication between job schedulers and workers. Nats does most of the heavy lifting, allowing us to keep the rest of the code simple and concise.
What is in name?
So why ClassWork? Well, this is simply because workers are simply "python classes" (The Class) whose "methods" become individual workers (The Students).
Get started
First let us create a simple worker
import asyncio
from classwork import ClassWork
class WorkerClass:
# Your worker...
# Notice that we expect workers to be async
async def add(self, a, b):
# the work!
resp = a + b
# simulate a long process
await asyncio.sleep(3)
# return results
return resp
# this is our nats server url
nats_url = "nats://127.0.0.1:4222"
# initialize ClassWork
class_work = ClassWork(nats_url=nats_url)
# init worker class
worker = WorkerClass()
# Ok, let us register things with asyncio
# notice the method 'class_work.register' is async!
asyncio.run(class_work.register(name="my-worker", worker_class=worker))
This is all the code we need to set up the worker. It is important to note the following:
- Worker Class methods should be asynchronous
- class_work.register is also async
- You will need NATS running with JetStream enabled!
The Job Scheduler
Now we need to create the job scheduler. Below is the code we need
import asyncio
import numpy as np
from pprint import pprint
from classwork import ClassWork
# init ClassWork
nats_url = "nats://127.0.0.1:4222"
class_work = ClassWork(nats_url=nats_url)
# Our callback function
# This is where complete work gets reported
async def report_callback(report_card):
print("We have a report!")
pprint(report_card)
# We need this function to create our job schedules
async def schedules():
# Assign a job
await class_work.assign(
# the task name
task="my_worker.add",
# arguments
args=[1, 2],
# the callback to report our results
report_callback=report_callback,
)
# Ok, let us create the schedules now
asyncio.run(schedules())
This code will create a task into NATS and the job workers (attentive students 😂) already listening will pick the task and run it, then publish their reports which is routed via NATS back to the scheduler (teacher?).
Take note of the following:
class_work.assignmust be run in async mode. So we have wrapped it in an async method. You can also useasyncio.rundirectly.- Naming your task is very important. This naming convection is unashamedly borrowed from moleculer. In this case, your task is "my_worker.add". This will route to any worker class registered with the name "my_worker" and method "add".
- Because all this traffic is routed via NATS, your arguments must be JSON serializable. Even though we use typ to handle edge cases like
sets, beware that there are limits to what you can pass in your arguments report_callbackmust be async. It is called with a 'report' of your task. A report card 😊 will look like the one below:argscan be passed as a list or dict. They will be treated as*argsif list and**kwargsif dict.
We have a report!
{'task': 'my_worker.add',
'duration': {'latency': {'request': '4 ms and 356 µs',
'response': '5 s and 4 ms'},
'my_worker.add': '3 s and 1 ms'},
'req_id': '8mYjJjM0kb5',
'response': 3}
Report Explanation
- duration: is a high precision (down to yoctoseconds) report of the time taken.
- latency: shows the time taken to route your "task request" to the worker and "task response" back to the scheduler. It is important to understand that since both worker and scheduler are disconnected, latency may also include delays of either to access the NATS network and thus does not specifically refer to network latency.
- req_id: is a unique id assigned to each job
- response: is the actual value returned by the worker
Try it
We have sample code in scheduler.py and worker.py
Metadata
Release files for classwork 0.0.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| classwork-0.0.7.tar.gz | 7.9 kB | Without provenance | Details for classwork-0.0.7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| classwork-0.0.7-py3-none-any.whl | Python 3 | none | any | Details for classwork-0.0.7-py3-none-any.whl |
Total release size: 17.1 kB
Release files / classwork-0.0.7.tar.gz
| Download URL | classwork-0.0.7.tar.gz |
|---|---|
| Size | 7.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
25f74c8a41830125e630a26b2313fbc5746e924dc533d7dee5e11bff62972d16
|
|
BLAKE2b-256 checksum How to use checksums |
cac7775bb2a79ea4c16f3e9b3dc5ed40625c56d5dd72c78ac9db94858619bb74
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.5.1 CPython/3.8.10 Linux/5.15.0-73-generic
|
Release files / classwork-0.0.7-py3-none-any.whl
| Download URL | classwork-0.0.7-py3-none-any.whl |
|---|---|
| Size | 9.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d177153da451a6501c5ccd9ae0096fc3c478fc61b317e88886ef6a2de92e01b2
|
|
BLAKE2b-256 checksum How to use checksums |
0c41cce65d9bcbba49130b062b82d74fe188b787b67e8adb92df78b62677e1d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.5.1 CPython/3.8.10 Linux/5.15.0-73-generic
|
Security for classwork 0.0.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.