Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
4506147
Implement ORB Worker Adapter
magniloquency Feb 10, 2026
783c10c
Add submit_tasks example to documentation and CI skip list
magniloquency Feb 10, 2026
9133f52
Merge branch 'main' into orb
magniloquency Feb 11, 2026
a1ff776
move orb/ and ami/ to driver/
magniloquency Feb 11, 2026
a46af96
remove superfluous checks in orb config
magniloquency Feb 11, 2026
e8ae3fc
move import
magniloquency Feb 11, 2026
2312d66
add a check for self._orb before returning machines
magniloquency Feb 11, 2026
89d964b
adjust security group rules
magniloquency Feb 11, 2026
248f2f7
move method
magniloquency Feb 11, 2026
0333ee7
rename no random worker ids to deterministic worker ids
magniloquency Feb 11, 2026
ce17847
add comment
magniloquency Feb 11, 2026
2796ead
run submit tasks in ci
magniloquency Feb 11, 2026
389a7b6
fix help text
magniloquency Feb 11, 2026
9eae58d
make _filter_data a static method
magniloquency Feb 11, 2026
d333899
refactor orb worker adapter polling to use constants
magniloquency Feb 11, 2026
562ec6a
flake8
magniloquency Feb 11, 2026
7a61c0e
don't touch skip examples file
magniloquency Feb 11, 2026
594342d
Merge branch 'main' of https://github.com/finos/opengris-scaler into orb
magniloquency Feb 12, 2026
350e840
bump minor version
magniloquency Feb 12, 2026
8ad0a61
Merge branch 'main' into orb
magniloquency Feb 13, 2026
a2d3856
docs: add worker adapter tutorials and update ORB integration details
magniloquency Feb 13, 2026
0329716
Merge branch 'orb' of https://github.com/magniloquency/scaler into orb
magniloquency Feb 13, 2026
c50fddb
refactor: move orb and ami drivers to src/scaler/drivers
magniloquency Feb 13, 2026
90f608a
Delete test.toml
magniloquency Feb 13, 2026
711e9e9
Merge branch 'main' into orb
magniloquency Feb 18, 2026
f789743
Refactor ORB worker adapter to use ZMQ-based protocol
magniloquency Feb 18, 2026
287cd7c
fix type error
magniloquency Feb 18, 2026
1235fae
fix type error
magniloquency Feb 18, 2026
8fda46c
Output ORB templates in snake_case
magniloquency Feb 20, 2026
5c5a76e
Simplify ORB driver config files
magniloquency Feb 20, 2026
2130431
Document default no-scaling policy and vanilla scaler example in work…
magniloquency Feb 20, 2026
2b54a3a
Merge branch 'main' into orb
sharpener6 Feb 23, 2026
4956370
Merge branch 'main' into orb
sharpener6 Feb 23, 2026
31de2fd
import documentation changes from #574
magniloquency Feb 24, 2026
8d893fe
Merge branch 'main' into orb
magniloquency Feb 25, 2026
759f21a
Merge main into orb, adopting worker_manager naming convention
magniloquency Mar 4, 2026
2928bef
Refactor ORB worker adapter to worker_manager_adapter naming and impr…
magniloquency Mar 4, 2026
d31f8ad
Refactor ORB config handling and simplify worker manager
magniloquency Mar 4, 2026
830d35f
Rename run_worker_adapter_orb to run_worker_manager_orb
magniloquency Mar 4, 2026
da6338c
Fix ORB template missing instance_types and broken region injection
magniloquency Mar 4, 2026
940f0d0
Use subnet_ids list field instead of subnet_id in ORB template
magniloquency Mar 4, 2026
ef54411
Add name field to ORBMachine to fix TypeError on deserialization
magniloquency Mar 4, 2026
e90f85c
Filter unknown keys when deserializing ORBMachine from dict
magniloquency Mar 4, 2026
15f3c42
Fix duplicate commands sent to adapter while previous command is in-f…
magniloquency Mar 4, 2026
1e931e1
Merge origin/main into orb, resolving conflicts
magniloquency Mar 13, 2026
31af0c7
upgrade to orb 1.2
magniloquency Mar 13, 2026
2e591d8
Migrate ORB worker manager from CLI subprocess to Python SDK
magniloquency Mar 13, 2026
1d50e13
Remove unused ORBMachine and ORBRequest types
magniloquency Mar 13, 2026
9948bf6
Fix WorkerAdapterConfig -> WorkerManagerConfig rename
magniloquency Mar 13, 2026
342735e
Work around ORB SDK app_config timing bug by writing temp config file
magniloquency Mar 13, 2026
983589f
Use ORB_CONFIG_DIR env var to inject config into ORB singleton
magniloquency Mar 13, 2026
c086599
Add template_id, image_id, provider_api to configuration dict for ORB…
magniloquency Mar 13, 2026
721acc5
Switch ORB storage from sql to json (SQLQueryBuilder is abstract in i…
magniloquency Mar 13, 2026
b2235e7
Monkey-patch ORB TemplateRepositoryImpl.get_by_id to accept plain str
magniloquency Mar 13, 2026
380831d
Fix ORB 1.2.2 missing add() method on TemplateRepositoryImpl
magniloquency Mar 13, 2026
67d1710
Patch Template.get_domain_events/clear_domain_events missing in ORB 1…
magniloquency Mar 13, 2026
d77718c
Merge origin/main into orb, resolving conflicts
magniloquency Mar 16, 2026
071d4bc
Upgrade ORB dependency to 1.3 and adopt context-manager SDK API
magniloquency Mar 17, 2026
feee439
Update ORB worker manager adapter for post-WorkerGroup protocol
magniloquency Mar 17, 2026
e785ca9
Add opengris-scaler 1.15.0 AMI and move packer files to orb adapter d…
magniloquency Mar 17, 2026
af01940
Fix ORB create_template call to use flat kwargs instead of nested con…
magniloquency Mar 17, 2026
89e01a7
Add validate_template call and logging after create_template in ORB s…
magniloquency Mar 17, 2026
1c3821e
Rename _worker_groups to _workers in ORB worker adapter
magniloquency Mar 17, 2026
6b69334
Remove hardcoded --num-of-workers from ORB cluster launch script
magniloquency Mar 17, 2026
949348e
Remove inaccurate worker ID tracking comment from ORB cluster launch …
magniloquency Mar 17, 2026
321ed08
Remove hardcoded attribute metadata from ORB create_template call
magniloquency Mar 17, 2026
90633b7
Merge main into orb branch
magniloquency Mar 17, 2026
3bd5c9c
Merge branch 'main' into orb
sharpener6 Mar 17, 2026
3f025de
Fix ymq import in ORB worker manager after e921fff3 refactor
magniloquency Mar 17, 2026
81d3cef
Merge main into orb, resolving documentation reorganization conflicts
magniloquency Mar 24, 2026
a79a3f6
Update orb-py dependency to 1.5.1
magniloquency Mar 24, 2026
325dcd4
Merge branch 'main' into orb
magniloquency Mar 24, 2026
1c034c1
Merge origin/main into orb
magniloquency Mar 26, 2026
602b736
Fix import order in orb worker_manager
magniloquency Mar 26, 2026
2f95e5b
Add orb worker manager support to unified entry points
magniloquency Mar 26, 2026
183f998
Remove dedicated scaler_worker_manager_orb entry point
magniloquency Mar 26, 2026
9fdcb20
Work around ORB skipping strategy defaults when config_dict is provided
magniloquency Mar 26, 2026
672ad72
Merge origin/main into orb
magniloquency Mar 27, 2026
2d50d26
Remove run_worker_manager_orb script
magniloquency Mar 27, 2026
1e8603b
Suppress repeated StartWorkers requests after TooManyWorkers
magniloquency Mar 27, 2026
4da853c
Lazy-import orb to fix CI test failures
magniloquency Mar 27, 2026
1177f26
Update ORB user data to use scaler_worker_manager with --mode fixed
magniloquency Mar 27, 2026
e254eac
fix io threads
magniloquency Mar 27, 2026
68d7e68
Add AMI 1.26.4 to docs and fix build.sh version path
magniloquency Mar 27, 2026
95f4fe7
Fix zero-worker default on single-core machines
magniloquency Mar 27, 2026
1fe9667
Fix TooManyWorkers suppression not working during EC2 boot
magniloquency Mar 27, 2026
d1d9633
Merge remote-tracking branch 'origin/main' into orb
magniloquency Mar 27, 2026
a0c9198
Rename ORB worker manager to orb_aws_ec2
magniloquency Mar 27, 2026
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
6 changes: 6 additions & 0 deletions .github/actions/run-test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ runs:
run: |
uv pip install --system -r examples/applications/requirements_applications.txt
uv pip install --system -r examples/ray_compat/requirements.txt
readarray -t skip_examples < examples/skip_examples.txt
for example in "./examples"/*.py; do
filename=$(basename "$example")
if [[ " ${skip_examples[*]} " =~ [[:space:]]${filename}[[:space:]] ]]; then
echo "Skipping $example"
continue
fi
echo "Running $example"
python $example
done
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ CMakeFiles/
src/scaler/protocol/capnp/*.c++
src/scaler/protocol/capnp/*.h

orb/logs/
orb/metrics/

# AWS HPC test-generated files
.scaler_aws_batch_config.json
.scaler_aws_hpc.env
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ The following table maps each Scaler command to its corresponding section name i
| `scaler_worker_manager symphony` | `[[worker_manager]]` + `type = "symphony"` |
| `scaler_worker_manager aws_raw_ecs` | `[[worker_manager]]` + `type = "aws_raw_ecs"` |
| `scaler_worker_manager aws_hpc` | `[[worker_manager]]` + `type = "aws_hpc"` |
| `scaler_worker_manager orb_aws_ec2` | `[[worker_manager]]` + `type = "orb_aws_ec2"` |

### Practical Scenarios & Examples

Expand Down Expand Up @@ -507,6 +508,40 @@ where `deepest_nesting_level` is the deepest nesting level a task has in your wo
workload that has
a base task that calls a nested task that calls another nested task, then the deepest nesting level is 2.

## ORB AWS EC2 integration

A Scaler scheduler can interface with ORB (Open Resource Broker) to dynamically provision and manage workers on AWS EC2 instances.

```bash
$ scaler_worker_manager orb_aws_ec2 tcp://127.0.0.1:2345 --image-id ami-0528819f94f4f5fa5
```

This will start an ORB AWS EC2 worker adapter that connects to the Scaler scheduler at `tcp://127.0.0.1:2345`. The scheduler can then request new workers from this adapter, which will be launched as EC2 instances.

The ORB AWS EC2 worker manager can also be included in a `scaler` all-in-one TOML config:

```toml
[scheduler]
scheduler_address = "tcp://127.0.0.1:2345"

[[worker_manager]]
type = "orb_aws_ec2"
scheduler_address = "tcp://127.0.0.1:2345"
image_id = "ami-0528819f94f4f5fa5"
instance_type = "t3.medium"
aws_region = "us-east-1"
```

### Configuration

The ORB AWS EC2 adapter requires `orb-py` and `boto3` to be installed. You can install them with:

```bash
$ pip install "opengris-scaler[orb_aws_ec2]"
```

For more details on configuring ORB AWS EC2, including AWS credentials and instance templates, please refer to the [ORB AWS EC2 Worker Adapter documentation](https://finos.github.io/opengris-scaler/tutorials/worker_manager_adapter/orb_aws_ec2.html).

## Worker Manager usage

> **Note**: This feature is experimental and may change in future releases.
Expand Down
78 changes: 77 additions & 1 deletion docs/source/tutorials/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ After installing ``opengris-scaler``, the following CLI commands are available f
* - :ref:`scaler_scheduler <cmd-scaler-scheduler>`
- Start only the scheduler process (and auto-start object storage when needed).
* - :ref:`scaler_worker_manager <cmd-scaler-worker-manager>`
- Start one worker manager using a subcommand (``baremetal_native``, ``symphony``, ``aws_raw_ecs``, ``aws_hpc``).
- Start one worker manager using a subcommand (``baremetal_native``, ``symphony``, ``aws_raw_ecs``, ``aws_hpc``, ``orb_aws_ec2``).
* - :ref:`scaler_object_storage_server <cmd-scaler-object-storage-server>`
- Start only the object storage server.
* - :ref:`scaler_top <cmd-scaler-top>`
Expand Down Expand Up @@ -53,6 +53,8 @@ All commands support ``--config``/``-c``. In practice, most deployments use TOML
- ``[[worker_manager]]`` + ``type = "aws_raw_ecs"``
* - ``scaler_worker_manager aws_hpc``
- ``[[worker_manager]]`` + ``type = "aws_hpc"``
* - ``scaler_worker_manager orb_aws_ec2``
- ``[[worker_manager]]`` + ``type = "orb_aws_ec2"``


.. _cmd-scaler:
Expand Down Expand Up @@ -352,6 +354,7 @@ Available subcommands:
- ``symphony``
- ``aws_raw_ecs``
- ``aws_hpc``
- ``orb_aws_ec2``

When ``--config``/``-c`` is supplied, ``scaler_worker_manager`` reads the ``[[worker_manager]]``
array from the TOML file and picks the entry whose ``type`` field matches the subcommand.
Expand Down Expand Up @@ -753,6 +756,79 @@ AWS Batch worker manager.
- ``60``
- Timeout for each submitted job.

Subcommand: ``orb_aws_ec2``
~~~~~~~~~~~~~~~~~~~~~~~~~~~

ORB (Open Resource Broker) worker manager — dynamically provisions workers on AWS EC2 instances.

.. code-block:: bash

$ scaler_worker_manager orb_aws_ec2 [options] <scheduler_address>

.. tabs::

.. group-tab:: command line

.. code-block:: bash

$ scaler_worker_manager orb_aws_ec2 tcp://127.0.0.1:6378 \
--object-storage-address tcp://127.0.0.1:6379 \
--image-id ami-0528819f94f4f5fa5 \
--instance-type t3.medium \
--aws-region us-east-1

.. group-tab:: config.toml

.. code-block:: toml

[[worker_manager]]
type = "orb_aws_ec2"
scheduler_address = "tcp://127.0.0.1:6378"
object_storage_address = "tcp://127.0.0.1:6379"
image_id = "ami-0528819f94f4f5fa5"
instance_type = "t3.medium"
aws_region = "us-east-1"

Run command:

.. code-block:: bash

$ scaler config.toml

.. list-table::
:header-rows: 1

* - Argument
- Required
- Default
- Description
* - ``--image-id``
- Yes
- -
- AMI ID for the worker EC2 instances.
* - ``--instance-type``
- No
- ``t2.micro``
- EC2 instance type.
* - ``--aws-region``
- No
- ``us-east-1``
- AWS region.
* - ``--key-name``
- No
- ``None``
- AWS key pair name. A temporary key pair is created if omitted.
* - ``--subnet-id``
- No
- ``None``
- AWS subnet ID. Defaults to the default subnet in the default VPC.
* - ``--security-group-ids``
- No
- ``[]``
- Comma-separated AWS security group IDs. A temporary group is created if omitted.

For full details, see :doc:`worker_managers/orb_aws_ec2`.


.. _cmd-scaler-object-storage-server:

Expand Down
2 changes: 1 addition & 1 deletion docs/source/tutorials/compatibility/ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Ray
Scaler is a lightweight distributed computation engine similar to Ray. Scaler supports many of the same concepts as Ray including
remote functions (known as tasks in Scaler), futures, cluster object storage, labels (known as capabilities in Scaler), and it comes with comparable monitoring tools.

Unlike Ray, Scaler supports both local clusters and also easily integrates with multiple cloud providers out of the box, including AWS EC2 and IBM Symphony,
Unlike Ray, Scaler supports both local clusters and also easily integrates with multiple cloud providers out of the box, including ORB (AWS EC2) and IBM Symphony,
with more providers planned for the future. You can view our `roadmap on GitHub <https://github.com/finos/opengris-scaler/discussions/333>`_
for details on upcoming cloud integrations.

Expand Down
5 changes: 5 additions & 0 deletions docs/source/tutorials/worker_managers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ Worker Managers Overview
- Offloads tasks to IBM Spectrum Symphony via the SOAM API.
- Concurrency-limited
- IBM Symphony
* - :doc:`ORB AWS EC2 <orb_aws_ec2>`
- Dynamically provisions workers on AWS EC2 instances using the ORB system.
- Dynamic (scheduler-driven)
- AWS EC2

Although worker managers target different infrastructures, many configuration options are shared.
See :doc:`Common Worker Manager Parameters <common_parameters>` for these shared settings.
Expand All @@ -72,4 +76,5 @@ The :ref:`scaler <cmd-scaler>` command boots the full stack from a single TOML c
aws_hpc_batch
aws_raw_ecs
symphony
orb_aws_ec2
common_parameters
145 changes: 145 additions & 0 deletions docs/source/tutorials/worker_managers/orb_aws_ec2.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
ORB AWS EC2 Worker Adapter
==========================

The ORB AWS EC2 worker adapter allows Scaler to dynamically provision workers on AWS EC2 instances using the ORB (Open Resource Broker) system. This is particularly useful for scaling workloads that require significant compute resources or specialized hardware available in the cloud.

This tutorial describes the steps required to get up and running with the ORB AWS EC2 adapter.

Requirements
------------

Before using the ORB AWS EC2 worker adapter, ensure the following requirements are met on the machine that will run the adapter:

1. **orb-py and boto3**: The ``orb-py`` and ``boto3`` packages must be installed. These can be installed using the ``orb_aws_ec2`` optional dependency of Scaler:

.. code-block:: bash

pip install "opengris-scaler[orb_aws_ec2]"

2. **AWS CLI**: The AWS Command Line Interface must be installed and configured with a default profile that has permissions to launch, describe, and terminate EC2 instances.

3. **Network Connectivity**: The adapter must be able to communicate with AWS APIs and the Scaler scheduler.

Getting Started
---------------

To start the ORB AWS EC2 worker adapter, use the ``scaler_worker_manager orb_aws_ec2`` subcommand:

.. code-block:: bash

scaler_worker_manager orb_aws_ec2 tcp://<SCHEDULER_EXTERNAL_IP>:8516 \
--object-storage-address tcp://<OSS_EXTERNAL_IP>:8517 \
--image-id ami-0528819f94f4f5fa5 \
--instance-type t3.medium \
--aws-region us-east-1 \
--logging-level INFO \
--task-timeout-seconds 60

Equivalent configuration using a TOML file with ``scaler``:

.. code-block:: toml

# stack.toml

[scheduler]
scheduler_address = "tcp://<SCHEDULER_EXTERNAL_IP>:8516"

[[worker_manager]]
type = "orb_aws_ec2"
scheduler_address = "tcp://<SCHEDULER_EXTERNAL_IP>:8516"
object_storage_address = "tcp://<OSS_EXTERNAL_IP>:8517"
image_id = "ami-0528819f94f4f5fa5"
instance_type = "t3.medium"
aws_region = "us-east-1"
logging_level = "INFO"
task_timeout_seconds = 60

.. code-block:: bash

scaler stack.toml

* ``tcp://<SCHEDULER_EXTERNAL_IP>:8516`` is the address workers will use to connect to the scheduler.
* ``tcp://<OSS_EXTERNAL_IP>:8517`` is the address workers will use to connect to the object storage server.
* New workers will be launched using the specified AMI and instance type.

Networking Configuration
------------------------

Workers launched by the ORB AWS EC2 adapter are EC2 instances and require an externally-reachable IP address for the scheduler.

* **Internal Communication**: If the machine running the scheduler is another EC2 instance in the same VPC, you can use EC2 private IP addresses.
* **Public Internet**: If communicating over the public internet, it is highly recommended to set up robust security rules and/or a VPN to protect the cluster.

Publicly Available AMIs
-----------------------

We regularly publish publicly available Amazon Machine Images (AMIs) with Python and ``opengris-scaler`` pre-installed.

.. list-table:: Available Public AMIs
:widths: 15 15 20 20 30
:header-rows: 1

* - Scaler Version
- Python Version
- Amazon Linux 2023 Version
- Date (MM/DD/YYYY)
- AMI ID (us-east-1)
* - 1.14.2
- 3.13
- 2023.10.20260120
- 01/30/2026
- ``ami-0528819f94f4f5fa5``
* - 1.15.0
- 3.13
- 2023.10.20260302.1
- 03/16/2026
- ``ami-044265172bea55d51``
* - 1.26.4
- 3.13
- 2023.10.20260302.1
- 03/26/2026
- ``ami-0b76605999d8f5d2b``

New AMIs will be added to this list as they become available.

Supported Parameters
--------------------

.. note::
For more details on how to configure Scaler, see the :doc:`../configuration` section.

The ORB AWS EC2 worker adapter supports ORB-specific configuration parameters as well as common worker adapter parameters.

ORB AWS EC2 Template Configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~

* ``--image-id`` (Required): AMI ID for the worker instances.
* ``--instance-type``: EC2 instance type (default: ``t2.micro``).
* ``--aws-region``: AWS region (default: ``us-east-1``).
* ``--key-name``: AWS key pair name for the instances. If not provided, a temporary key pair will be created and deleted on cleanup.
* ``--subnet-id``: AWS subnet ID where the instances will be launched. If not provided, it attempts to discover the default subnet in the default VPC.
* ``--security-group-ids``: Comma-separated list of AWS security group IDs.
* ``--allowed-ip``: IP address to allow in the security group (if created automatically). Defaults to the adapter's external IP.
* ``--orb-config-path``: Path to the ORB root directory (default: ``src/scaler/drivers/orb``).

Common Parameters
~~~~~~~~~~~~~~~~~

For a full list of common parameters including networking, worker configuration, and logging, see :doc:`common_parameters`.

Cleanup
-------

The ORB AWS EC2 worker adapter is designed to be self-cleaning, but it is important to be aware of the resources it manages:

* **Key Pairs**: If a ``--key-name`` is not provided, the adapter creates a temporary AWS key pair.
* **Security Groups**: If ``--security-group-ids`` are not provided, the adapter creates a temporary security group to allow communication.
* **Launch Templates**: ORB may additionally create EC2 Launch Templates as part of the machine provisioning process.

The adapter attempts to delete these temporary resources and terminate all launched EC2 instances when it shuts down gracefully. However, in the event of an ungraceful crash or network failure, some resources may persist in your AWS account.

.. tip::
It is recommended to periodically check your AWS console for any orphaned resources (instances, security groups, key pairs, or launch templates) and clean them up manually if necessary to avoid unexpected costs.

.. warning::
**Subnet and Security Groups**: Currently, specifying ``--subnet-id`` or ``--security-group-ids`` via configuration might not have the intended effect as the adapter is designed to auto-discover or create these resources. Specifically, the adapter may still attempt to use default subnets or create its own temporary security groups regardless of these parameters.
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,15 @@ graphblas = [
aws = [
"boto3",
]
orb_aws_ec2 = [
"orb-py~=1.5.1; python_version >= '3.10'",
"boto3; python_version >= '3.10'",
]
all = [
"opengris-scaler[aws]",
"opengris-scaler[graphblas]",
"opengris-scaler[gui]",
"opengris-scaler[orb_aws_ec2]",
"opengris-scaler[uvloop]",
]

Expand Down
2 changes: 1 addition & 1 deletion src/scaler/config/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
# WORKER SPECIFIC OPTIONS

# number of workers, echo worker use 1 process
DEFAULT_MAX_TASK_CONCURRENCY = os.cpu_count() - 1
DEFAULT_MAX_TASK_CONCURRENCY = os.cpu_count()

# number of seconds that worker agent send heartbeat to scheduler
DEFAULT_HEARTBEAT_INTERVAL_SECONDS = 2
Expand Down
Loading
Loading