arpakitlib 1.7.66__py3-none-any.whl → 1.7.124__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arpakitlib/_arpakit_project_template/example.env +4 -0
- arpakitlib/_arpakit_project_template/manage/hello_world.py +2 -2
- arpakitlib/_arpakit_project_template/manage/json_beutify.py +4 -4
- arpakitlib/_arpakit_project_template/manage/poetry_config.sh +2 -0
- arpakitlib/_arpakit_project_template/manage/poetry_self_add_plugin_export.sh +2 -0
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_1.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_2.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_3.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_4.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_5.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_6.py +4 -4
- arpakitlib/_arpakit_project_template/manage/sandbox/sandbox_7.py +4 -4
- arpakitlib/_arpakit_project_template/resource/static/healthcheck +1 -0
- arpakitlib/_arpakit_project_template/src/admin1/__init__.py +0 -0
- arpakitlib/_arpakit_project_template/src/admin1/add_admin_in_app.py +25 -0
- arpakitlib/_arpakit_project_template/src/admin1/admin_auth.py +29 -0
- arpakitlib/_arpakit_project_template/src/admin1/model_view.py +19 -0
- arpakitlib/_arpakit_project_template/src/api/auth.py +1 -6
- arpakitlib/_arpakit_project_template/src/api/create_api_app.py +13 -52
- arpakitlib/_arpakit_project_template/src/api/event.py +51 -2
- arpakitlib/_arpakit_project_template/src/api/router/main_router.py +3 -0
- arpakitlib/_arpakit_project_template/src/api/router/v1/get_api_error_info.py +6 -4
- arpakitlib/_arpakit_project_template/src/api/start_api_for_dev_with_reload.py +12 -4
- arpakitlib/_arpakit_project_template/src/api/{start_api_for_dev.py → start_api_for_dev_without_reload.py} +3 -3
- arpakitlib/_arpakit_project_template/src/api/transmitted_api_data.py +4 -0
- arpakitlib/_arpakit_project_template/src/business_service/hello_world.py +12 -0
- arpakitlib/_arpakit_project_template/{manage/logging_check.py → src/core/check_logging.py} +3 -3
- arpakitlib/_arpakit_project_template/src/core/check_settings.py +12 -0
- arpakitlib/_arpakit_project_template/src/core/generate_settings_env_example.py +16 -0
- arpakitlib/_arpakit_project_template/src/core/settings.py +13 -5
- arpakitlib/_arpakit_project_template/src/core/util.py +0 -18
- arpakitlib/_arpakit_project_template/{manage/sqlalchemy_db_check_conn.py → src/db/check_conn_sqlalchemy_db.py} +2 -1
- arpakitlib/_arpakit_project_template/src/db/const.py +0 -0
- arpakitlib/_arpakit_project_template/src/db/init_sqlalchemy_db.py +11 -0
- arpakitlib/_arpakit_project_template/src/db/reinit_sqlalchemy_db.py +13 -0
- arpakitlib/_arpakit_project_template/src/db/util.py +21 -0
- arpakitlib/_arpakit_project_template/src/operation_execution/operation_executor.py +6 -4
- arpakitlib/_arpakit_project_template/src/operation_execution/scheduled_operations.py +3 -3
- arpakitlib/_arpakit_project_template/src/operation_execution/{start_operation_executor_worker_for_dev.py → start_operation_executor_worker.py} +7 -5
- arpakitlib/_arpakit_project_template/src/operation_execution/start_scheduled_operation_creator_worker.py +19 -0
- arpakitlib/_arpakit_project_template/src/operation_execution/util.py +0 -0
- arpakitlib/_arpakit_project_template/src/tg_bot/__init__.py +0 -0
- arpakitlib/_arpakit_project_template/src/tg_bot/router/__init__.py +0 -0
- arpakitlib/_arpakit_project_template/src/tg_bot/start_tg_bot.py +0 -0
- arpakitlib/api_key_util.py +12 -0
- arpakitlib/ar_additional_model_util.py +18 -1
- arpakitlib/ar_arpakit_lib_module_util.py +13 -1
- arpakitlib/ar_arpakit_schedule_uust_api_client_util.py +24 -3
- arpakitlib/ar_arpakitlib_cli_util.py +2 -0
- arpakitlib/ar_base_worker_util.py +67 -18
- arpakitlib/ar_exception_util.py +13 -0
- arpakitlib/ar_fastapi_util.py +129 -98
- arpakitlib/ar_file_util.py +2 -0
- arpakitlib/ar_func_util.py +55 -0
- arpakitlib/ar_json_util.py +11 -9
- arpakitlib/ar_need_type_util.py +8 -1
- arpakitlib/ar_openai_api_client_util.py +16 -2
- arpakitlib/ar_operation_execution_util.py +143 -141
- arpakitlib/ar_schedule_uust_api_client_util.py +13 -6
- arpakitlib/ar_settings_util.py +24 -5
- arpakitlib/ar_sqlalchemy_model_util.py +37 -7
- arpakitlib/ar_ssh_runner_util.py +2 -2
- arpakitlib/ar_str_util.py +30 -1
- arpakitlib/ar_type_util.py +52 -7
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/METADATA +27 -20
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/RECORD +70 -62
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/WHEEL +1 -1
- arpakitlib/_arpakit_project_template/AUTHOR.md +0 -4
- arpakitlib/_arpakit_project_template/manage/example_nginx_proxy.nginx +0 -14
- arpakitlib/_arpakit_project_template/manage/example_poetry_arpakitlib.sh +0 -1
- arpakitlib/_arpakit_project_template/manage/example_pyproject.toml +0 -18
- arpakitlib/_arpakit_project_template/manage/example_systemd.service +0 -12
- arpakitlib/_arpakit_project_template/manage/requirements.txt +0 -209
- arpakitlib/_arpakit_project_template/manage/settings_check.py +0 -10
- arpakitlib/_arpakit_project_template/manage/settings_generate_env_example.py +0 -13
- arpakitlib/_arpakit_project_template/manage/sqlalchemy_db_init.py +0 -10
- arpakitlib/_arpakit_project_template/manage/sqlalchemy_db_reinit.py +0 -10
- arpakitlib/_arpakit_project_template/src/operation_execution/start_scheduled_operation_creator_worker_for_dev.py +0 -16
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/LICENSE +0 -0
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/NOTICE +0 -0
- {arpakitlib-1.7.66.dist-info → arpakitlib-1.7.124.dist-info}/entry_points.txt +0 -0
@@ -1,13 +1,10 @@
|
|
1
1
|
import asyncio
|
2
|
-
import importlib
|
3
|
-
from contextlib import suppress
|
4
2
|
from datetime import datetime
|
5
3
|
from functools import lru_cache
|
6
4
|
|
7
5
|
from arpakitlib.ar_datetime_util import now_dt
|
8
6
|
from arpakitlib.ar_file_storage_in_dir_util import FileStorageInDir
|
9
7
|
from arpakitlib.ar_logging_util import setup_normal_logging
|
10
|
-
from arpakitlib.ar_sqlalchemy_util import SQLAlchemyDB
|
11
8
|
from arpakitlib.ar_type_util import raise_if_none
|
12
9
|
from src.core.settings import get_cached_settings
|
13
10
|
|
@@ -43,21 +40,6 @@ def get_cached_dump_file_storage_in_dir() -> FileStorageInDir:
|
|
43
40
|
return create_dump_file_storage_in_dir()
|
44
41
|
|
45
42
|
|
46
|
-
def create_sqlalchemy_db() -> SQLAlchemyDB:
|
47
|
-
with suppress(Exception):
|
48
|
-
importlib.import_module("src.db.sqlalchemy_model")
|
49
|
-
|
50
|
-
return SQLAlchemyDB(
|
51
|
-
db_url=get_cached_settings().sql_db_url,
|
52
|
-
db_echo=get_cached_settings().sql_db_echo
|
53
|
-
)
|
54
|
-
|
55
|
-
|
56
|
-
@lru_cache()
|
57
|
-
def get_cached_sqlalchemy_db() -> SQLAlchemyDB:
|
58
|
-
return create_sqlalchemy_db()
|
59
|
-
|
60
|
-
|
61
43
|
def now_local_dt() -> datetime:
|
62
44
|
raise_if_none(get_cached_settings().local_timezone_as_pytz)
|
63
45
|
return now_dt(tz=get_cached_settings().local_timezone_as_pytz)
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from src.core.settings import get_cached_settings
|
2
|
+
from src.core.util import setup_logging
|
3
|
+
from src.db.util import get_cached_sqlalchemy_db
|
4
|
+
|
5
|
+
|
6
|
+
def __reinit_sqlalchemy_db():
|
7
|
+
setup_logging()
|
8
|
+
get_cached_settings().raise_if_mode_type_not_prod()
|
9
|
+
get_cached_sqlalchemy_db().reinit()
|
10
|
+
|
11
|
+
|
12
|
+
if __name__ == '__main__':
|
13
|
+
__reinit_sqlalchemy_db()
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import importlib
|
2
|
+
from contextlib import suppress
|
3
|
+
from functools import lru_cache
|
4
|
+
|
5
|
+
from arpakitlib.ar_sqlalchemy_util import SQLAlchemyDB
|
6
|
+
from src.core.settings import get_cached_settings
|
7
|
+
|
8
|
+
|
9
|
+
def create_sqlalchemy_db() -> SQLAlchemyDB:
|
10
|
+
with suppress(Exception):
|
11
|
+
importlib.import_module("src.db.sqlalchemy_model")
|
12
|
+
|
13
|
+
return SQLAlchemyDB(
|
14
|
+
db_url=get_cached_settings().sql_db_url,
|
15
|
+
db_echo=get_cached_settings().sql_db_echo
|
16
|
+
)
|
17
|
+
|
18
|
+
|
19
|
+
@lru_cache()
|
20
|
+
def get_cached_sqlalchemy_db() -> SQLAlchemyDB:
|
21
|
+
return create_sqlalchemy_db()
|
@@ -1,14 +1,16 @@
|
|
1
|
+
from sqlalchemy.orm import Session
|
2
|
+
|
1
3
|
from arpakitlib.ar_operation_execution_util import BaseOperationExecutor
|
2
4
|
from arpakitlib.ar_sqlalchemy_model_util import OperationDBM
|
3
5
|
|
4
6
|
|
5
7
|
class OperationExecutor(BaseOperationExecutor):
|
6
|
-
def sync_execute_operation(self, operation_dbm: OperationDBM) -> OperationDBM:
|
8
|
+
def sync_execute_operation(self, operation_dbm: OperationDBM, session: Session) -> OperationDBM:
|
7
9
|
# ...
|
8
|
-
operation_dbm = super().sync_execute_operation(operation_dbm=operation_dbm)
|
10
|
+
operation_dbm = super().sync_execute_operation(operation_dbm=operation_dbm, session=session)
|
9
11
|
return operation_dbm
|
10
12
|
|
11
|
-
async def async_execute_operation(self, operation_dbm: OperationDBM) -> OperationDBM:
|
13
|
+
async def async_execute_operation(self, operation_dbm: OperationDBM, session: Session) -> OperationDBM:
|
12
14
|
# ...
|
13
|
-
operation_dbm = await super().async_execute_operation(operation_dbm=operation_dbm)
|
15
|
+
operation_dbm = await super().async_execute_operation(operation_dbm=operation_dbm, session=session)
|
14
16
|
return operation_dbm
|
@@ -4,14 +4,14 @@ from arpakitlib.ar_operation_execution_util import ScheduledOperation, every_tim
|
|
4
4
|
between_different_times_is_time_func
|
5
5
|
from arpakitlib.ar_sqlalchemy_model_util import BaseOperationTypes
|
6
6
|
|
7
|
-
|
7
|
+
SCHEDULED_OPERATIONS = []
|
8
8
|
|
9
9
|
healthcheck_1_scheduled_operation = ScheduledOperation(
|
10
10
|
type=BaseOperationTypes.healthcheck_,
|
11
11
|
input_data={"healthcheck_1": "healthcheck_1"},
|
12
12
|
is_time_func=every_timedelta_is_time_func(td=timedelta(seconds=15))
|
13
13
|
)
|
14
|
-
|
14
|
+
SCHEDULED_OPERATIONS.append(healthcheck_1_scheduled_operation)
|
15
15
|
|
16
16
|
healthcheck_2_scheduled_operation = ScheduledOperation(
|
17
17
|
type=BaseOperationTypes.healthcheck_,
|
@@ -22,4 +22,4 @@ healthcheck_2_scheduled_operation = ScheduledOperation(
|
|
22
22
|
),
|
23
23
|
timeout_after_creation=timedelta(seconds=60)
|
24
24
|
)
|
25
|
-
|
25
|
+
SCHEDULED_OPERATIONS.append(healthcheck_2_scheduled_operation)
|
@@ -1,17 +1,19 @@
|
|
1
1
|
from arpakitlib.ar_operation_execution_util import OperationExecutorWorker
|
2
|
-
from src.core.
|
2
|
+
from src.core.settings import get_cached_settings
|
3
|
+
from src.core.util import setup_logging
|
4
|
+
from src.db.util import get_cached_sqlalchemy_db
|
3
5
|
from src.operation_execution.operation_executor import OperationExecutor
|
4
6
|
|
5
7
|
|
6
|
-
def
|
8
|
+
def start_operation_executor_worker():
|
7
9
|
setup_logging()
|
10
|
+
get_cached_settings().raise_if_mode_type_prod()
|
8
11
|
worker = OperationExecutorWorker(
|
9
12
|
sqlalchemy_db=get_cached_sqlalchemy_db(),
|
10
|
-
operation_executor=OperationExecutor(sqlalchemy_db=get_cached_sqlalchemy_db())
|
11
|
-
filter_operation_types=None
|
13
|
+
operation_executor=OperationExecutor(sqlalchemy_db=get_cached_sqlalchemy_db())
|
12
14
|
)
|
13
15
|
worker.sync_safe_run()
|
14
16
|
|
15
17
|
|
16
18
|
if __name__ == '__main__':
|
17
|
-
|
19
|
+
start_operation_executor_worker()
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from arpakitlib.ar_operation_execution_util import ScheduledOperationCreatorWorker
|
2
|
+
from src.core.settings import get_cached_settings
|
3
|
+
from src.core.util import setup_logging
|
4
|
+
from src.db.util import get_cached_sqlalchemy_db
|
5
|
+
from src.operation_execution.scheduled_operations import SCHEDULED_OPERATIONS
|
6
|
+
|
7
|
+
|
8
|
+
def start_scheduled_operation_creator_worker():
|
9
|
+
setup_logging()
|
10
|
+
get_cached_settings().raise_if_mode_type_prod()
|
11
|
+
worker = ScheduledOperationCreatorWorker(
|
12
|
+
sqlalchemy_db=get_cached_sqlalchemy_db(),
|
13
|
+
scheduled_operations=SCHEDULED_OPERATIONS
|
14
|
+
)
|
15
|
+
worker.sync_safe_run()
|
16
|
+
|
17
|
+
|
18
|
+
if __name__ == '__main__':
|
19
|
+
start_scheduled_operation_creator_worker()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
arpakitlib/api_key_util.py
CHANGED
@@ -2,8 +2,20 @@ from uuid import uuid4
|
|
2
2
|
|
3
3
|
from arpakitlib.ar_datetime_util import now_utc_dt
|
4
4
|
|
5
|
+
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
6
|
+
|
5
7
|
|
6
8
|
def generate_api_key() -> str:
|
7
9
|
return (
|
8
10
|
f"apikey{str(uuid4()).replace('-', '')}{str(now_utc_dt().timestamp()).replace('.', '')}"
|
9
11
|
)
|
12
|
+
|
13
|
+
|
14
|
+
def __example():
|
15
|
+
for i in range(5):
|
16
|
+
api_key = generate_api_key()
|
17
|
+
print(f"API-key: {api_key}")
|
18
|
+
|
19
|
+
|
20
|
+
if __name__ == '__main__':
|
21
|
+
__example()
|
@@ -3,6 +3,8 @@ from typing import Any
|
|
3
3
|
|
4
4
|
from pydantic import BaseModel, ConfigDict
|
5
5
|
|
6
|
+
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
7
|
+
|
6
8
|
|
7
9
|
class BaseAM(BaseModel):
|
8
10
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
@@ -16,7 +18,22 @@ class BaseAM(BaseModel):
|
|
16
18
|
|
17
19
|
|
18
20
|
def __example():
|
19
|
-
|
21
|
+
class UserAM(BaseAM):
|
22
|
+
id: int
|
23
|
+
name: str
|
24
|
+
email: str
|
25
|
+
|
26
|
+
@property
|
27
|
+
def bus_data_age(self) -> int | None:
|
28
|
+
return self.bus_data.get("age")
|
29
|
+
|
30
|
+
user = UserAM(id=1, name="John Doe", email="john.doe@example.com")
|
31
|
+
print(user.name) # John Doe
|
32
|
+
|
33
|
+
# bus_data
|
34
|
+
user.bus_data["age"] = 22
|
35
|
+
print(user.bus_data) # {'age': '22'}
|
36
|
+
print(user.bus_data_age) # 22
|
20
37
|
|
21
38
|
|
22
39
|
if __name__ == '__main__':
|
@@ -79,6 +79,12 @@ class ArpakitLibModules(NamedTuple):
|
|
79
79
|
if arpakit_lib_module.module_has_error
|
80
80
|
]
|
81
81
|
|
82
|
+
def have_modules_with_error(self) -> bool:
|
83
|
+
for arpakit_lib_module in self.arpakit_lib_modules:
|
84
|
+
if arpakit_lib_module.module_has_error:
|
85
|
+
return True
|
86
|
+
return False
|
87
|
+
|
82
88
|
def module_name_to_module_exception(self, *, filter_module_has_error: bool = False) -> dict[str, BaseException]:
|
83
89
|
if filter_module_has_error:
|
84
90
|
return {
|
@@ -144,7 +150,13 @@ def get_arpakit_lib_modules() -> ArpakitLibModules:
|
|
144
150
|
|
145
151
|
|
146
152
|
def __example():
|
147
|
-
|
153
|
+
for module_name, d in (
|
154
|
+
get_arpakit_lib_modules().module_name_to_module_version_and_module_has_errors().items()
|
155
|
+
):
|
156
|
+
print(module_name)
|
157
|
+
print(d)
|
158
|
+
print()
|
159
|
+
print("have_modules_with_error", get_arpakit_lib_modules().have_modules_with_error())
|
148
160
|
|
149
161
|
|
150
162
|
if __name__ == '__main__':
|
@@ -17,7 +17,7 @@ from pydantic import ConfigDict, BaseModel
|
|
17
17
|
|
18
18
|
from arpakitlib.ar_dict_util import combine_dicts
|
19
19
|
from arpakitlib.ar_enumeration_util import Enumeration
|
20
|
-
from arpakitlib.ar_json_util import
|
20
|
+
from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
|
21
21
|
from arpakitlib.ar_sleep_util import async_safe_sleep
|
22
22
|
from arpakitlib.ar_type_util import raise_for_type
|
23
23
|
|
@@ -53,7 +53,7 @@ class BaseAPIModel(BaseModel):
|
|
53
53
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
54
54
|
|
55
55
|
def simple_json(self) -> str:
|
56
|
-
return
|
56
|
+
return safely_transfer_obj_to_json_str(self.model_dump(mode="json"))
|
57
57
|
|
58
58
|
|
59
59
|
class GroupAPIModel(BaseAPIModel):
|
@@ -521,7 +521,28 @@ def __example():
|
|
521
521
|
|
522
522
|
|
523
523
|
async def __async_example():
|
524
|
-
|
524
|
+
client = ARPAKITScheduleUUSTAPIClient(api_key="TEST_API_KEY", use_cache=True)
|
525
|
+
|
526
|
+
healthcheck = await client.healthcheck()
|
527
|
+
print(f"Healthcheck: {healthcheck}")
|
528
|
+
|
529
|
+
auth_healthcheck = await client.auth_healthcheck()
|
530
|
+
print(f"Auth Healthcheck: {auth_healthcheck}")
|
531
|
+
|
532
|
+
current_week = await client.get_current_week()
|
533
|
+
print(f"Текущая неделя: {current_week.simple_json() if current_week else 'Не найдено'}")
|
534
|
+
|
535
|
+
current_semester = await client.get_current_semester()
|
536
|
+
print(f"Текущий семестр: {current_semester.simple_json() if current_semester else 'Не найдено'}")
|
537
|
+
|
538
|
+
groups = await client.get_groups()
|
539
|
+
print(f"Группы: {[group.simple_json() for group in groups]}")
|
540
|
+
|
541
|
+
teachers = await client.get_teachers()
|
542
|
+
print(f"Преподаватели: {[teacher.simple_json() for teacher in teachers]}")
|
543
|
+
|
544
|
+
weather = await client.get_weather_in_ufa()
|
545
|
+
print(f"Погода в Уфе: {weather.simple_json()}")
|
525
546
|
|
526
547
|
|
527
548
|
if __name__ == '__main__':
|
@@ -7,6 +7,8 @@ from arpakitlib.ar_need_type_util import parse_need_type, NeedTypes
|
|
7
7
|
from arpakitlib.ar_parse_command import parse_command
|
8
8
|
from arpakitlib.ar_str_util import raise_if_string_blank
|
9
9
|
|
10
|
+
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
11
|
+
|
10
12
|
|
11
13
|
def execute_arpakitlib_cli(*, full_command: str | None = None):
|
12
14
|
if full_command is None:
|
@@ -6,27 +6,58 @@ import multiprocessing
|
|
6
6
|
import threading
|
7
7
|
from abc import ABC
|
8
8
|
from datetime import timedelta
|
9
|
+
from random import randint
|
10
|
+
from typing import Any
|
11
|
+
from uuid import uuid4
|
9
12
|
|
13
|
+
from arpakitlib.ar_datetime_util import now_utc_dt
|
10
14
|
from arpakitlib.ar_enumeration_util import Enumeration
|
15
|
+
from arpakitlib.ar_func_util import is_async_function, is_sync_function
|
11
16
|
from arpakitlib.ar_sleep_util import sync_safe_sleep, async_safe_sleep
|
12
17
|
|
13
18
|
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
14
19
|
|
15
20
|
|
16
21
|
class BaseWorker(ABC):
|
17
|
-
def __init__(
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
*,
|
25
|
+
timeout_after_run=timedelta(seconds=0.3),
|
26
|
+
timeout_after_err_in_run=timedelta(seconds=1),
|
27
|
+
startup_funcs: list[Any] | None = None,
|
28
|
+
worker_name: str | None = None
|
29
|
+
):
|
30
|
+
if startup_funcs is None:
|
31
|
+
startup_funcs = []
|
32
|
+
self.startup_funcs = startup_funcs
|
33
|
+
if worker_name is None:
|
34
|
+
worker_name = self.__class__.__name__
|
35
|
+
self.worker_name = worker_name
|
36
|
+
self.worker_creation_dt = now_utc_dt()
|
37
|
+
self.worker_id = f"{str(uuid4()).replace('-', '')}_{randint(1000, 99999)}"
|
38
|
+
self.worker_fullname = (
|
39
|
+
f"{self.worker_name}_{self.worker_creation_dt.isoformat()}_{self.worker_id}"
|
40
|
+
)
|
41
|
+
self._logger = logging.getLogger(self.worker_fullname)
|
42
|
+
self.timeout_after_run = timeout_after_run
|
43
|
+
self.timeout_after_err_in_run = timeout_after_err_in_run
|
44
|
+
|
45
|
+
def sync_run_startup_funcs(self):
|
46
|
+
for startup_func in self.startup_funcs:
|
47
|
+
if is_async_function(startup_func):
|
48
|
+
asyncio.run(startup_func())
|
49
|
+
elif is_sync_function(startup_func):
|
50
|
+
startup_func()
|
51
|
+
else:
|
52
|
+
raise TypeError("no sync and not async")
|
22
53
|
|
23
54
|
def sync_on_startup(self):
|
24
|
-
|
55
|
+
self.sync_run_startup_funcs()
|
25
56
|
|
26
57
|
def sync_run(self):
|
27
|
-
self._logger.info("hello world")
|
58
|
+
self._logger.info(f"hello world, im {self.worker_fullname}")
|
28
59
|
|
29
|
-
def
|
60
|
+
def sync_on_error(self, exception: BaseException, **kwargs):
|
30
61
|
pass
|
31
62
|
|
32
63
|
def sync_safe_run(self):
|
@@ -42,20 +73,29 @@ class BaseWorker(ABC):
|
|
42
73
|
except BaseException as exception:
|
43
74
|
self._logger.error("error in sync_run", exc_info=exception)
|
44
75
|
try:
|
45
|
-
self.
|
76
|
+
self.sync_on_error(exception=exception)
|
46
77
|
except BaseException as exception_:
|
47
|
-
self._logger.error("error in
|
78
|
+
self._logger.error("error in sync_on_error", exc_info=exception_)
|
48
79
|
raise exception_
|
49
|
-
|
50
|
-
|
80
|
+
sync_safe_sleep(self.timeout_after_err_in_run)
|
81
|
+
sync_safe_sleep(self.timeout_after_run)
|
82
|
+
|
83
|
+
async def async_run_startup_funcs(self):
|
84
|
+
for startup_func in self.startup_funcs:
|
85
|
+
if is_async_function(startup_func):
|
86
|
+
await startup_func()
|
87
|
+
elif is_sync_function(startup_func):
|
88
|
+
startup_func()
|
89
|
+
else:
|
90
|
+
raise TypeError("no sync and not async")
|
51
91
|
|
52
92
|
async def async_on_startup(self):
|
53
|
-
|
93
|
+
await self.async_run_startup_funcs()
|
54
94
|
|
55
95
|
async def async_run(self):
|
56
|
-
self._logger.info("hello world")
|
96
|
+
self._logger.info(f"hello world, im {self.worker_fullname}")
|
57
97
|
|
58
|
-
async def
|
98
|
+
async def async_on_error(self, exception: BaseException, **kwargs):
|
59
99
|
pass
|
60
100
|
|
61
101
|
async def async_safe_run(self):
|
@@ -71,12 +111,12 @@ class BaseWorker(ABC):
|
|
71
111
|
except BaseException as exception:
|
72
112
|
self._logger.error("error in async_run", exc_info=exception)
|
73
113
|
try:
|
74
|
-
await self.
|
114
|
+
await self.async_on_error(exception=exception)
|
75
115
|
except BaseException as exception_:
|
76
|
-
self._logger.error("error in
|
116
|
+
self._logger.error("error in async_on_error", exc_info=exception_)
|
77
117
|
raise exception_
|
78
|
-
if self.timeout_after_err_in_run is not None:
|
79
118
|
await async_safe_sleep(self.timeout_after_err_in_run)
|
119
|
+
await async_safe_sleep(self.timeout_after_run)
|
80
120
|
|
81
121
|
|
82
122
|
class SafeRunInBackgroundModes(Enumeration):
|
@@ -107,6 +147,15 @@ def safe_run_worker_in_background(*, worker: BaseWorker, mode: str) -> (
|
|
107
147
|
return res
|
108
148
|
|
109
149
|
|
150
|
+
def safe_run_workers_in_background(
|
151
|
+
*, workers: list[BaseWorker], mode: str
|
152
|
+
) -> list[asyncio.Task] | list[threading.Thread] | list[multiprocessing.Process]:
|
153
|
+
res = []
|
154
|
+
for worker in workers:
|
155
|
+
res.append(safe_run_worker_in_background(worker=worker, mode=mode))
|
156
|
+
return res
|
157
|
+
|
158
|
+
|
110
159
|
def __example():
|
111
160
|
pass
|
112
161
|
|
arpakitlib/ar_exception_util.py
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
import traceback
|
2
2
|
|
3
|
+
_ARPAKIT_LIB_MODULE_VERSION = "3.0"
|
4
|
+
|
3
5
|
|
4
6
|
def exception_to_traceback_str(exception: BaseException) -> str:
|
5
7
|
return "".join(traceback.format_exception(type(exception), exception, exception.__traceback__))
|
8
|
+
|
9
|
+
|
10
|
+
def __example():
|
11
|
+
try:
|
12
|
+
raise Exception()
|
13
|
+
except Exception as exception:
|
14
|
+
print(exception_to_traceback_str(exception))
|
15
|
+
|
16
|
+
|
17
|
+
if __name__ == '__main__':
|
18
|
+
__example()
|