Skip to content

Commit

Permalink
Merge pull request #74 from Miksus/docs/fix
Browse files Browse the repository at this point in the history
DOCS: Update documentation
  • Loading branch information
Miksus authored Aug 14, 2022
2 parents 18d0cb1 + 640cc17 commit 8fa4aea
Show file tree
Hide file tree
Showing 16 changed files with 531 additions and 87 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def cleanup():
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_title = "Rocketry:<br>Advanced Scheduler"
html_title = "Rocketry"
html_theme = 'sphinx_book_theme'
html_logo = "logo.svg"
html_favicon = 'favicon.ico'
Expand Down
127 changes: 127 additions & 0 deletions docs/cookbook/bigger_applications.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
Bigger Applications
===================

When your project grows in size you might want to
put the application to multiple files.

.. code-block::
.
├── app
│   ├── __init__.py
│   ├── main.py
│   ├── conditions.py
│   ├── arguments.py
│   └── tasks
│   ├── __init__.py
│   ├── morning.py
│   └── evening.py
.. note::

We use ``__init__.py`` files to make
importing easier from the tasks. This
structure enables us importing the conditions
by ``from app.conditions import my_cond``.

Files
-----

Here is a quick explanation of the files and what
you could put in each:

.. glossary::

``__init__.py``

Marks the directory as a package. You can leave
these empty.

``app/main.py``

Entry point to the application. This

It could look like:

.. code-block::
from rocketry import Rocketry
from app.tasks import morning, evening
app = Rocketry()
# Set the task groups
app.include_group(morning.group)
app.include_group(evening.group)
if __name__ == "__main__":
app.run()
``app/tasks/...``

Put your tasks here. Use also groups and
put the groups in the app in ``app/main.py``
to avoid problems in importing.

For example, ``app/tasks/evening.py`` could look like this:

.. code-block::
from rocketry import Grouper
from rocketry.args import FuncArg
from app.conditions import my_cond
from app.parameters import get_value
group = Grouper()
@group.task(my_cond)
def do_things(arg=FuncArg(get_value)):
...
``app/conditions.py``

Put custom conditions here.

For example:

.. code-block::
from rocketry import Grouper
group = Grouper()
@group.cond()
def my_cond():
return True or False
We created a group to conveniently declare
the function to be a condition. We don't
need to include this group to the app.

``app/arguments.py``

Put custom parameters here. For example:

.. code-block::
def get_value():
return "Hello"
You can also nest these and pass an argument as
to another argument with ``FuncArg`` similarly
we set in the task.

Running
-------

Then you can run this as a Python module:

.. code-block::
python -m app.main
.. note::

You can also turn this to a package using ``setup.py``
or add CLI by creating ``__main__.py`` file.
90 changes: 90 additions & 0 deletions docs/cookbook/fastapi.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@

Integrate FastAPI
=================

The simplest way to combine FastAPI app with Rocketry app
is to start both as async tasks. You can modify the Rocketry's
runtime session in FastAPI. There is an existing example project:
`Rocketry with FastAPI (and React) <https://github.com/Miksus/rocketry-with-fastapi>`_

First, we create a simple Rocketry app
(let's call this ``scheduler.py``):

.. code-block:: python
# Create Rocketry app
from rocketry import Rocketry
app = Rocketry(config={"task_execution": "async"})
# Create some tasks
@app.task('every 5 seconds')
async def do_things():
...
if __name__ == "__main__":
app.run()
Then we create a FastAPI app and manipulate the Rocketry
app in it (let's call this ``api.py``):

.. code-block:: python
# Create FastAPI app
from fastapi import FastAPI
app = FastAPI()
# Import the Rocketry app
from scheduler import app as app_rocketry
session = app_rocketry.session
@app.get("/my-route")
async def get_tasks():
return session.tasks
@app.post("/my-route")
async def manipulate_session():
for task in session.tasks:
...
if __name__ == "__main__":
app.run()
Then we combine these in one module
(let's call this ``main.py``):

.. code-block:: python
import asyncio
import uvicorn
from api import app as app_fastapi
from scheduler import app as app_rocketry
class Server(uvicorn.Server):
"""Customized uvicorn.Server
Uvicorn server overrides signals and we need to include
Rocketry to the signals."""
def handle_exit(self, sig: int, frame) -> None:
app_rocketry.session.shut_down()
return super().handle_exit(sig, frame)
async def main():
"Run scheduler and the API"
server = Server(config=uvicorn.Config(app_fastapi, workers=1, loop="asyncio"))
api = asyncio.create_task(server.serve())
sched = asyncio.create_task(app_rocketry.serve())
await asyncio.wait([sched, api])
if __name__ == "__main__":
asyncio.run(main())
Note that we need to subclass the ``uvicorn.Server`` in order
to make sure the scheduler is also closed when the FastAPI app
closes. Otherwise the system might not respond on keyboard interrupt.
9 changes: 9 additions & 0 deletions docs/cookbook/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Cookbook
========

.. toctree::
:maxdepth: 3
:caption: Contents:

bigger_applications
fastapi
35 changes: 0 additions & 35 deletions docs/examples/demos/fastapi.rst

This file was deleted.

15 changes: 11 additions & 4 deletions docs/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,18 @@
Examples
========

.. toctree::
:maxdepth: 3
:caption: Contents:
Example Projects
^^^^^^^^^^^^^^^^

demos/fastapi
.. glossary::

`Rocketry with FastAPI (and React) <https://github.com/Miksus/rocketry-with-fastapi>`_

Rocketry template that has FastAPI (REST API) integrated and also has web UI built
with React.

Example Snippets
^^^^^^^^^^^^^^^^

**Minimal example:**

Expand Down
5 changes: 0 additions & 5 deletions docs/handbooks/conditions/classes.rst

This file was deleted.

11 changes: 11 additions & 0 deletions docs/handbooks/conditions/classes/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

Condition Classes
=================

Condition classes are the low level mechanics of the condition
system. All conditions are instances of the condition classes.

There are also time period utilities that are used in the
time related conditions. They determine whether a given time
is inside a given time period, such as a given day of month,
day of week, between
30 changes: 22 additions & 8 deletions docs/handbooks/conditions/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ could be *time is now between 8 am and 2 pm* (12-hour clock)
or *time is now between 08:00 and 14:00* (24-hour clock).
If current time is inside this range, the condition
is true and if not, then it's false. If this is a condition
for a task, it runs if the the current time is in the range.
for a task, the task is run if the the current time is in the range.

The conditions can be combinded using logical operations:
**AND**, **OR**, **NOT**. They also can be nested using
Expand All @@ -21,12 +21,26 @@ There are three ways of creating conditions in Rocketry:
- Condition API
- Condition classes

All of the above produce instances of conditions that
can be used as the starting conditions of tasks or the
shut down condition of a scheduler. The condition syntax
turns the condition strings to the condition API's
components and condition API's components are turned to
instances of the actual conditions.
All of the above generate condition instances that
can be used as:

- The start condition of a task (task starts if the condition is true)
- The end condition of a task (task terminates if the condition is true and the task is running)
- The shut condition of the scheduler (scheduler shuts down if the condition is true, useful in testing)

When evaluating a condition, the system uses method ``observe`` to get
the state of the condition. You can test the status of a condition by:

.. code-block:: python
>>> from rocketry.conds import time_of_day
>>> condition = time_of_day.between("10:00", "14:00")
>>> condition.observe()
True
The above returns ``True`` if your current time is between 10:00 (10 AM) and 14:00 (2 PM).
Some conditions might rely on a task or the session
(passed as ``.observe(task=task, session=session)``).


.. toctree::
Expand All @@ -35,5 +49,5 @@ instances of the actual conditions.

api/index
syntax/index
classes
classes/index
comparisons
1 change: 1 addition & 0 deletions docs/handbooks/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ operates.
:maxdepth: 3
:caption: Contents:

structure
task/index
conditions/index
config
Expand Down
4 changes: 3 additions & 1 deletion docs/handbooks/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ Here is an example to log to a CSV file:
handler = RepoHandler(repo=repo)
logger.addHandler(handler)
Another common pattern is to log the records to a
SQL database. This can be done with SQLAlchemy:

Expand All @@ -112,7 +113,8 @@ SQL database. This can be done with SQLAlchemy:
repo = SQLRepo(engine=engine, table="tasks", if_missing="create", model=MinimalRecord, id_field="created")
handler = RepoHandler(repo=repo)
logging.addHandler(handler)
logger.addHandler(handler)
Read more about repositories from `Red Bird's documentation <https://red-bird.readthedocs.io/>`_.

Expand Down
Loading

0 comments on commit 8fa4aea

Please sign in to comment.