Skip to content

Commit a4f3949

Browse files
author
Joel Collins
committed
Expanded docs
1 parent 17d4f23 commit a4f3949

File tree

4 files changed

+74
-2
lines changed

4 files changed

+74
-2
lines changed

docs/basic_usage/action_tasks.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Action tasks
2+
============
3+
4+
Many actions in your LabThing may perform tasks that take a long time (compared to the expected response time of a web request). For example, if you were to implement a timelapse action, this inherently runs over a long time.
5+
6+
This introduces a couple of problems. Firstly, a request that triggers a long function will, by default, block the Python interpreter for the duration of the function. This usually causes the connection to timeout, and the response will never be revieved.
7+
8+
Tasks are introduced to manage long-running functions in a way that does not block HTTP requests. Any API Action will automatically run as a task.
9+
10+
Internally, the :class:`labthings.LabThing` object stores a list of all requested actions, and their states. This state stores the running status of the action (if itis idle, running, error, or success), information about the start and end times, a unique task ID, and, upon completion, the return value of the long-running function.
11+
12+
By using tasks, a function can be started in the background, and it's return value fetched at a later time once it has reported success. If a long-running action is started by some client, it should note the ID returned in the action state JSON, and use this to periodically check on the status of that particular action.
13+
14+
API routes have been created to allow checking the state of all actions (GET ``/actions``), a particular task by ID (GET ``/actions/<action_id>``), and terminating or removing individual tasks (DELETE ``/actions/<action_id>``).
15+
16+
All Actions will return a serialized representation of the task, when your POST request returns. If the task completes within a default timeout period (usually 1 second) then the completed Action representation will be returned. If the task is still running after this timeout period, the "in-progress" Action representation will be returned. The final output value can then be retrieved at a later time.
17+
18+
Most users will not need to create instances of this class. Instead, they will be created automatically when a function is started by an API Action view.
19+
20+
.. autoclass:: labthings.tasks.TaskThread
21+
:members:
22+
23+
24+
Accessing the current task
25+
++++++++++++++++++++++++++
26+
27+
A function running inside a :class:`labthings.tasks.TaskThread` is able to access the instance it is running in using the :meth:`labthings.current_task` function. This allows the state of the Action to be modified freely.
28+
29+
.. autofunction:: labthings.current_task
30+
:noindex:
31+
32+
33+
Updating task progress
34+
++++++++++++++++++++++
35+
36+
Some client applications may be able to display progress bars showing the progress of an action. Implementing progress updates in your actions is made easy with the :py:meth:`labthings.update_task_progress` function. This function takes a single argument, which is the action progress as an integer percent (0 - 100).
37+
38+
If your long running function was started within a background task, this function will update the state of the corresponding action object. If your function is called outside of a long-running task (e.g. by some internal code, not the web API), then this function will silently do nothing.
39+
40+
.. autofunction:: labthings.update_task_progress
41+
:noindex:

docs/basic_usage/synchronisation.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
Synchronisation objects
2+
=======================
3+
4+
5+
Locks
6+
-----
7+
8+
Locks have been implemented to solve a distinct issue, most obvious when considering action tasks. During a long task, it may be necesarry to block any completing interaction with the LabThing hardware.
9+
10+
The :py:class:`labthings.StrictLock` class is a form of re-entrant lock. Once acquired by a thread, that thread can re-acquire the same lock. This means that other requests or actions will block, or timeout, but the action which acquired the lock is able to re-acquire it.
11+
12+
.. autoclass:: labthings.StrictLock
13+
:members:
14+
:noindex:
15+
16+
A CompositeLock allows grouping multiple locks to be simultaneously acquired and released.
17+
18+
.. autoclass:: labthings.CompositeLock
19+
:members:
20+
:noindex:
21+
22+
23+
Per-Client events
24+
-----------------
25+
26+
.. autoclass:: labthings.ClientEvent
27+
:members:
28+
:noindex:

src/labthings/tasks/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
]
88

99
from .pool import (
10+
Pool,
1011
current_task,
1112
update_task_progress,
1213
update_task_data,
1314
)
14-
from .thread import TaskKillException
15+
from .thread import TaskThread, TaskKillException
1516

1617
# Legacy alias
1718
ThreadTerminationError = TaskKillException

src/labthings/tasks/thread.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ class TaskKillException(SystemExit):
1616

1717

1818
class TaskThread(threading.Thread):
19-
""" """
19+
"""
20+
A native thread with extra functionality for tracking progress and thread termination.
21+
"""
2022

2123
def __init__(self, target=None, name=None, args=None, kwargs=None, daemon=True):
2224
threading.Thread.__init__(

0 commit comments

Comments
 (0)