Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KOJO-217 | Start of Usage Patterns guide #118

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ A distributed task manager.

Real-world use cases for Kōjō and instructions for getting Kōjō up and running in your project can be found at [KojoFitness](https://github.com/neighborhoods/KojoFitness).

A guide/reference for common usage patterns can be found [here](docs/Usage%20Patterns.md).

## Debugging Kōjō
XDebug version greater than `xdebug-2.7.0alpha1` is required when trying to debug Kōjō. This version of XDebug resolves issues (https://bugs.xdebug.org/938) caused by the way the Kōjō forks using `pcntl`.

Expand Down
49 changes: 49 additions & 0 deletions docs/Usage Patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Kojo usage patterns

Kojo makes as few assumptions as possible about your workload, and is thus flexible enough to support many different patterns of usage.
"Using" a given "pattern" is a combination of a) configuring your `kojo_job_type` values correctly, and b) interacting with Kojo's runtime API a certain way.
This document will enumerate various patterns and provide guidance on when and how to use them.

As a simple example, imagine a workload where we need to perform an action, say, every day at midnight (UTC).
When creating the job type, we'd use the [Job Type Service and Registrar](https://github.com/neighborhoods/kojo/tree/5.x/src/Api/V1/Job/Type), and the most important piece of configuration here would be to `->setCronExpression('0 0 * * *')`, resulting in Kojo adding a row to `kojo_job` at midnight UTC every day.
Though not strictly necessary, it's also good practice to `->setCanWorkInParallel(false)` and `->setScheduleLimit(1)` (if not to guard against situations where there are multiple instances of this job (e.g. if a user dynamically schedules them), then at least to signal to posterity how this job type is intended to work).
At runtime, the only interaction with Kojo's API necessary is to signal state changes of the job with the [Worker Service](https://github.com/neighborhoods/kojo/blob/5.x/src/Api/V1/Worker/ServiceInterface.php) (e.g. `->requestCompleteSuccess()->applyRequest()`).

### Continuous Singleton

This pattern is for situations where you need to do some work continuously, and having a single process is sufficient compute for keeping up with the work (e.g. polling something for changes and then processing those changes).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to include a visual diagram of each pattern something like

Class Diagram

Made this with https://plantuml.com/activity-diagram-beta and put linked it as an image via https://github.com/Zingam/UML-in-Markdown


#### Kojo Job Type Configuration

Field | Value | Notes
--- | --- | ---
can_work_in_parallel | |
cron_expression | |
schedule_limit | |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of expressing this as a quick reference table. If we transpose the rows we can add all the patterns so they can be viewed side-by-side to compare them easier:

pattern can_work_in_parallel cron_expression schedule_limit
static schedule false 0 0 * * * 1
continuous singleton false * * * * * 1
delagated linear clone true * * * * * 10
dynamically scheduled true null null


#### Kojo Runtime API Interactions

None.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would go in here normally?

  • happy path: ->requestCompleteSuccess()->applyRequest()
  • error path: ->requestCompleteFailed()->applyRequest()
  • DLC Patten ->schduleNewJob($job)?


#### Variations

* Guaranteeing that at most one will be running
* Set `can_work_in_parallel: true` and `schedule_limit: 1`
* Guaranteeing that at least one will be running
* Set `cron_expression: '* * * * *'`
* (or similar, depending on the maximum time between runs you're comfortable with)
* Being a good citizen
* You can get away with just having one instance of this job running forever, but Kojo relies on [cooperative multitasking](https://en.wikipedia.org/wiki/Cooperative_multitasking), so it's a good idea to have your worker gracefully "bow out" and return control to kojo
* Changes required for this are using the Kojo Runtime API to
* [Schedule a copy of yourself](https://github.com/neighborhoods/kojo/blob/5.x/src/Api/V1/Worker/ServiceInterface.php#L31)
* requestCompleteSuccess()

#### Examples

https://github.com/neighborhoods/KojoFitness/blob/master/UseCase45/src/V1/Worker.php


TODO:
* other patterns
* extract common stuff like "being a good citizen" out of individual sections
* create a decision flowchart for which pattern to use