diff --git a/goosebit.yaml b/goosebit.yaml index d017677b..4e930bd0 100644 --- a/goosebit.yaml +++ b/goosebit.yaml @@ -16,6 +16,9 @@ # Frequency that devices should check for available updates. poll_time: 00:01:00 +# Limit the number of updates that run at the same time. Can be used to avoid overloading the update server. +#max_concurrent_updates: 1000 + # Whether to track the IP of the device when it polls. Useful for debugging, but can be turned off for privacy. #track_device_ip: true diff --git a/goosebit/settings/schema.py b/goosebit/settings/schema.py index 303f306f..7dd5c683 100644 --- a/goosebit/settings/schema.py +++ b/goosebit/settings/schema.py @@ -43,6 +43,8 @@ class GooseBitSettings(BaseSettings): poll_time: str = "00:01:00" + max_concurrent_updates: int = 1000 + device_auth: DeviceAuthSettings = DeviceAuthSettings() secret_key: Annotated[OctKey, BeforeValidator(OctKey.import_key)] = secrets.token_hex(16) diff --git a/goosebit/updater/controller/v1/routes.py b/goosebit/updater/controller/v1/routes.py index b4dec0de..8aa2f2ea 100644 --- a/goosebit/updater/controller/v1/routes.py +++ b/goosebit/updater/controller/v1/routes.py @@ -51,16 +51,18 @@ async def polling(request: Request, device: Device = Depends(get_device)): # won't confirm a successful testing (might be a bug/problem in swupdate) handling_type, software = await DeviceManager.get_update(device) if handling_type != HandlingType.SKIP and software is not None: - links["deploymentBase"] = { - "href": str( - request.url_for( - "deployment_base", - dev_id=device.id, - action_id=software.id, + number_of_running = await Device.filter(last_state=UpdateStateEnum.RUNNING).count() + if number_of_running < config.max_concurrent_updates or device.last_state == UpdateStateEnum.RUNNING: + links["deploymentBase"] = { + "href": str( + request.url_for( + "deployment_base", + dev_id=device.id, + action_id=software.id, + ) ) - ) - } - logger.info(f"Forced: update available, device={device.id}") + } + logger.info(f"Forced: update available, device={device.id}") return { "config": {"polling": {"sleep": sleep}}, @@ -123,7 +125,8 @@ async def deployment_feedback(_: Request, data: FeedbackSchema, action_id: int, else: # edge case where device update mode got changed while update was running logging.warning( - f"Updating rollout success stats failed, action_id={action_id}, device={device.id}" # noqa: E501 + f"Updating rollout success stats failed, action_id={action_id}, device={device.id}" + # noqa: E501 ) if reported_software: @@ -143,7 +146,8 @@ async def deployment_feedback(_: Request, data: FeedbackSchema, action_id: int, else: # edge case where device update mode got changed while update was running logging.warning( - f"Updating rollout failure stats failed, action_id={action_id}, device={device.id}" # noqa: E501 + f"Updating rollout failure stats failed, action_id={action_id}, device={device.id}" + # noqa: E501 ) software_version = reported_software.version if reported_software else None