Standardize async offloading behind shared executor helper
This commit is contained in:
@@ -21,6 +21,7 @@ directory traversal.
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from app.utils.async_utils import run_blocking
|
||||
import configparser
|
||||
import contextlib
|
||||
import io
|
||||
@@ -1098,7 +1099,7 @@ async def list_inactive_jails(
|
||||
inactive jails.
|
||||
"""
|
||||
loop = asyncio.get_event_loop()
|
||||
parsed_result: tuple[dict[str, dict[str, str]], dict[str, str]] = await loop.run_in_executor(
|
||||
parsed_result: tuple[dict[str, dict[str, str]], dict[str, str]] = await run_blocking(
|
||||
None, _parse_jails_sync, Path(config_dir)
|
||||
)
|
||||
all_jails, source_files = parsed_result
|
||||
@@ -1156,7 +1157,7 @@ async def activate_jail(
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
raise JailNotFoundInConfigError(name)
|
||||
@@ -1168,7 +1169,7 @@ async def activate_jail(
|
||||
# ---------------------------------------------------------------------- #
|
||||
# Pre-activation validation — collect warnings but do not block #
|
||||
# ---------------------------------------------------------------------- #
|
||||
validation_result: JailValidationResult = await loop.run_in_executor(
|
||||
validation_result: JailValidationResult = await run_blocking(
|
||||
None, _validate_jail_config_sync, Path(config_dir), name
|
||||
)
|
||||
warnings: list[str] = [f"{i.field}: {i.message}" for i in validation_result.issues]
|
||||
@@ -1208,12 +1209,12 @@ async def activate_jail(
|
||||
# we can restore it if activation fails. #
|
||||
# ---------------------------------------------------------------------- #
|
||||
local_path = Path(config_dir) / "jail.d" / f"{name}.local"
|
||||
original_content: bytes | None = await loop.run_in_executor(
|
||||
original_content: bytes | None = await run_blocking(
|
||||
None,
|
||||
lambda: local_path.read_bytes() if local_path.exists() else None,
|
||||
)
|
||||
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_write_local_override_sync,
|
||||
Path(config_dir),
|
||||
@@ -1361,7 +1362,7 @@ async def _rollback_activation_async(
|
||||
|
||||
# Step 1 — restore original file (or delete it).
|
||||
try:
|
||||
await loop.run_in_executor(None, _restore_local_file_sync, local_path, original_content)
|
||||
await run_blocking( _restore_local_file_sync, local_path, original_content)
|
||||
log.info("jail_activation_rollback_file_restored", jail=name)
|
||||
except ConfigWriteError as exc:
|
||||
log.error("jail_activation_rollback_restore_failed", jail=name, error=str(exc))
|
||||
@@ -1417,7 +1418,7 @@ async def deactivate_jail(
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
raise JailNotFoundInConfigError(name)
|
||||
@@ -1426,7 +1427,7 @@ async def deactivate_jail(
|
||||
if name not in active_names:
|
||||
raise JailAlreadyInactiveError(name)
|
||||
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_write_local_override_sync,
|
||||
Path(config_dir),
|
||||
@@ -1475,7 +1476,7 @@ async def delete_jail_local_override(
|
||||
_safe_jail_name(name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
all_jails, _source_files = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _source_files = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
|
||||
if name not in all_jails:
|
||||
raise JailNotFoundInConfigError(name)
|
||||
@@ -1486,7 +1487,7 @@ async def delete_jail_local_override(
|
||||
|
||||
local_path = Path(config_dir) / "jail.d" / f"{name}.local"
|
||||
try:
|
||||
await loop.run_in_executor(None, lambda: local_path.unlink(missing_ok=True))
|
||||
await run_blocking( lambda: local_path.unlink(missing_ok=True))
|
||||
except OSError as exc:
|
||||
raise ConfigWriteError(f"Failed to delete {local_path}: {exc}") from exc
|
||||
|
||||
@@ -1515,7 +1516,7 @@ async def validate_jail_config(
|
||||
"""
|
||||
_safe_jail_name(name)
|
||||
loop = asyncio.get_event_loop()
|
||||
return await loop.run_in_executor(
|
||||
return await run_blocking(
|
||||
None,
|
||||
_validate_jail_config_sync,
|
||||
Path(config_dir),
|
||||
@@ -1554,7 +1555,7 @@ async def rollback_jail(
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Write enabled=false — this must succeed even when fail2ban is down.
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_write_local_override_sync,
|
||||
Path(config_dir),
|
||||
@@ -1792,11 +1793,11 @@ async def list_filters(
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Run the synchronous scan in a thread-pool executor.
|
||||
raw_filters: list[tuple[str, str, str, bool, str]] = await loop.run_in_executor(None, _parse_filters_sync, filter_d)
|
||||
raw_filters: list[tuple[str, str, str, bool, str]] = await run_blocking( _parse_filters_sync, filter_d)
|
||||
|
||||
# Fetch active jail names and their configs concurrently.
|
||||
all_jails_result, active_names = await asyncio.gather(
|
||||
loop.run_in_executor(None, _parse_jails_sync, Path(config_dir)),
|
||||
run_blocking( _parse_jails_sync, Path(config_dir)),
|
||||
_get_active_jail_names(socket_path),
|
||||
)
|
||||
all_jails, _source_files = all_jails_result
|
||||
@@ -1891,12 +1892,12 @@ async def get_filter(
|
||||
else:
|
||||
raise FilterNotFoundError(base_name)
|
||||
|
||||
content, has_local, source_path = await loop.run_in_executor(None, _read)
|
||||
content, has_local, source_path = await run_blocking( _read)
|
||||
|
||||
cfg = conffile_parser.parse_filter_file(content, name=base_name, filename=f"{base_name}.conf")
|
||||
|
||||
all_jails_result, active_names = await asyncio.gather(
|
||||
loop.run_in_executor(None, _parse_jails_sync, Path(config_dir)),
|
||||
run_blocking( _parse_jails_sync, Path(config_dir)),
|
||||
_get_active_jail_names(socket_path),
|
||||
)
|
||||
all_jails, _source_files = all_jails_result
|
||||
@@ -1988,7 +1989,7 @@ async def update_filter(
|
||||
|
||||
filter_d = Path(config_dir) / "filter.d"
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, _write_filter_local_sync, filter_d, base_name, content)
|
||||
await run_blocking( _write_filter_local_sync, filter_d, base_name, content)
|
||||
|
||||
if do_reload:
|
||||
try:
|
||||
@@ -2045,7 +2046,7 @@ async def create_filter(
|
||||
raise FilterAlreadyExistsError(req.name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, _check_not_exists)
|
||||
await run_blocking( _check_not_exists)
|
||||
|
||||
# Validate regex patterns.
|
||||
patterns: list[str] = list(req.failregex) + list(req.ignoreregex)
|
||||
@@ -2063,7 +2064,7 @@ async def create_filter(
|
||||
)
|
||||
content = conffile_parser.serialize_filter_config(cfg)
|
||||
|
||||
await loop.run_in_executor(None, _write_filter_local_sync, filter_d, req.name, content)
|
||||
await run_blocking( _write_filter_local_sync, filter_d, req.name, content)
|
||||
|
||||
if do_reload:
|
||||
try:
|
||||
@@ -2130,7 +2131,7 @@ async def delete_filter(
|
||||
|
||||
log.info("filter_local_deleted", filter=base_name, path=str(local_path))
|
||||
|
||||
await loop.run_in_executor(None, _delete)
|
||||
await run_blocking( _delete)
|
||||
|
||||
|
||||
async def assign_filter_to_jail(
|
||||
@@ -2168,7 +2169,7 @@ async def assign_filter_to_jail(
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Verify the jail exists in config.
|
||||
all_jails, _src = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _src = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
if jail_name not in all_jails:
|
||||
raise JailNotFoundInConfigError(jail_name)
|
||||
|
||||
@@ -2181,9 +2182,9 @@ async def assign_filter_to_jail(
|
||||
if not conf_exists and not local_exists:
|
||||
raise FilterNotFoundError(req.filter_name)
|
||||
|
||||
await loop.run_in_executor(None, _check_filter)
|
||||
await run_blocking( _check_filter)
|
||||
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_set_jail_local_key_sync,
|
||||
Path(config_dir),
|
||||
@@ -2657,10 +2658,10 @@ async def list_actions(
|
||||
action_d = Path(config_dir) / "action.d"
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
raw_actions: list[tuple[str, str, str, bool, str]] = await loop.run_in_executor(None, _parse_actions_sync, action_d)
|
||||
raw_actions: list[tuple[str, str, str, bool, str]] = await run_blocking( _parse_actions_sync, action_d)
|
||||
|
||||
all_jails_result, active_names = await asyncio.gather(
|
||||
loop.run_in_executor(None, _parse_jails_sync, Path(config_dir)),
|
||||
run_blocking( _parse_jails_sync, Path(config_dir)),
|
||||
_get_active_jail_names(socket_path),
|
||||
)
|
||||
all_jails, _source_files = all_jails_result
|
||||
@@ -2754,12 +2755,12 @@ async def get_action(
|
||||
else:
|
||||
raise ActionNotFoundError(base_name)
|
||||
|
||||
content, has_local, source_path = await loop.run_in_executor(None, _read)
|
||||
content, has_local, source_path = await run_blocking( _read)
|
||||
|
||||
cfg = conffile_parser.parse_action_file(content, name=base_name, filename=f"{base_name}.conf")
|
||||
|
||||
all_jails_result, active_names = await asyncio.gather(
|
||||
loop.run_in_executor(None, _parse_jails_sync, Path(config_dir)),
|
||||
run_blocking( _parse_jails_sync, Path(config_dir)),
|
||||
_get_active_jail_names(socket_path),
|
||||
)
|
||||
all_jails, _source_files = all_jails_result
|
||||
@@ -2842,7 +2843,7 @@ async def update_action(
|
||||
|
||||
action_d = Path(config_dir) / "action.d"
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, _write_action_local_sync, action_d, base_name, content)
|
||||
await run_blocking( _write_action_local_sync, action_d, base_name, content)
|
||||
|
||||
if do_reload:
|
||||
try:
|
||||
@@ -2895,7 +2896,7 @@ async def create_action(
|
||||
raise ActionAlreadyExistsError(req.name)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, _check_not_exists)
|
||||
await run_blocking( _check_not_exists)
|
||||
|
||||
cfg = ActionConfig(
|
||||
name=req.name,
|
||||
@@ -2911,7 +2912,7 @@ async def create_action(
|
||||
)
|
||||
content = conffile_parser.serialize_action_config(cfg)
|
||||
|
||||
await loop.run_in_executor(None, _write_action_local_sync, action_d, req.name, content)
|
||||
await run_blocking( _write_action_local_sync, action_d, req.name, content)
|
||||
|
||||
if do_reload:
|
||||
try:
|
||||
@@ -2976,7 +2977,7 @@ async def delete_action(
|
||||
|
||||
log.info("action_local_deleted", action=base_name, path=str(local_path))
|
||||
|
||||
await loop.run_in_executor(None, _delete)
|
||||
await run_blocking( _delete)
|
||||
|
||||
|
||||
async def assign_action_to_jail(
|
||||
@@ -3014,7 +3015,7 @@ async def assign_action_to_jail(
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
all_jails, _src = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _src = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
if jail_name not in all_jails:
|
||||
raise JailNotFoundInConfigError(jail_name)
|
||||
|
||||
@@ -3027,7 +3028,7 @@ async def assign_action_to_jail(
|
||||
):
|
||||
raise ActionNotFoundError(req.action_name)
|
||||
|
||||
await loop.run_in_executor(None, _check_action)
|
||||
await run_blocking( _check_action)
|
||||
|
||||
# Build the action string with optional parameters.
|
||||
if req.params:
|
||||
@@ -3036,7 +3037,7 @@ async def assign_action_to_jail(
|
||||
else:
|
||||
action_entry = req.action_name
|
||||
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_append_jail_action_sync,
|
||||
Path(config_dir),
|
||||
@@ -3094,11 +3095,11 @@ async def remove_action_from_jail(
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
all_jails, _src = await loop.run_in_executor(None, _parse_jails_sync, Path(config_dir))
|
||||
all_jails, _src = await run_blocking( _parse_jails_sync, Path(config_dir))
|
||||
if jail_name not in all_jails:
|
||||
raise JailNotFoundInConfigError(jail_name)
|
||||
|
||||
await loop.run_in_executor(
|
||||
await run_blocking(
|
||||
None,
|
||||
_remove_jail_action_sync,
|
||||
Path(config_dir),
|
||||
|
||||
Reference in New Issue
Block a user