arpakitlib 1.7.256__py3-none-any.whl → 1.8.0__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 → _arpakit_project_template_v1}/README.md +1 -1
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/admin1/add_admin_in_app.py +6 -12
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/admin1/admin_auth.py +2 -6
- arpakitlib/_arpakit_project_template_v1/admin1/model_view.py +95 -0
- arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/alembic/env.py +3 -3
- arpakitlib/_arpakit_project_template_v1/api/asgi.py +3 -0
- arpakitlib/_arpakit_project_template_v1/api/auth.py +244 -0
- arpakitlib/_arpakit_project_template_v1/api/const.py +18 -0
- arpakitlib/_arpakit_project_template_v1/api/create_api_app.py +72 -0
- arpakitlib/_arpakit_project_template_v1/api/event.py +69 -0
- arpakitlib/_arpakit_project_template_v1/api/exception.py +39 -0
- arpakitlib/_arpakit_project_template_v1/api/exception_handler.py +297 -0
- arpakitlib/_arpakit_project_template_v1/api/openapi_ui.py +28 -0
- arpakitlib/_arpakit_project_template_v1/api/response.py +27 -0
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/api/router/main_router.py +3 -2
- arpakitlib/_arpakit_project_template_v1/api/router/v1/arpakitlib_.py +27 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/check_auth.py +30 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/get_errors_info.py +24 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/healthcheck.py +21 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/main_router.py +54 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/now_utc_datetime.py +21 -0
- arpakitlib/_arpakit_project_template_v1/api/router/v1/raise_fake_error.py +21 -0
- arpakitlib/_arpakit_project_template_v1/api/schema/base_schema.py +26 -0
- arpakitlib/_arpakit_project_template_v1/api/schema/common/in_.py +5 -0
- arpakitlib/_arpakit_project_template_v1/api/schema/common/out.py +60 -0
- arpakitlib/_arpakit_project_template_v1/api/schema/v1/in_.py +5 -0
- arpakitlib/_arpakit_project_template_v1/api/schema/v1/out.py +53 -0
- arpakitlib/_arpakit_project_template_v1/api/transmitted_api_data.py +66 -0
- arpakitlib/_arpakit_project_template_v1/arpakitlib_project_template.json +3 -0
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/business_service/hello_world.py +1 -1
- arpakitlib/_arpakit_project_template_v1/business_service/remove_operations.py +51 -0
- arpakitlib/_arpakit_project_template_v1/command/alembic_history.sh +2 -0
- arpakitlib/_arpakit_project_template_v1/command/alembic_revision_autogenerate.sh +2 -0
- arpakitlib/{_arpakit_project_template/manage/json_beautify.py → _arpakit_project_template_v1/command/beautify_json.py} +2 -2
- arpakitlib/{_arpakit_project_template/src/core/_check_logging.py → _arpakit_project_template_v1/command/check_logging.py} +3 -3
- arpakitlib/_arpakit_project_template_v1/command/check_sqlalchemy_db.py +11 -0
- arpakitlib/_arpakit_project_template_v1/command/drop_json_db.py +13 -0
- arpakitlib/_arpakit_project_template_v1/command/drop_sqlalchemy_db.py +14 -0
- arpakitlib/{_arpakit_project_template/src/core/_generate_settings_env_example.py → _arpakit_project_template_v1/command/generate_settings_env_example.py} +4 -4
- arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/hello_world.py +2 -2
- arpakitlib/_arpakit_project_template_v1/command/init_json_db.py +11 -0
- arpakitlib/_arpakit_project_template_v1/command/init_sqlalchemy_db.py +11 -0
- arpakitlib/_arpakit_project_template_v1/command/reinit_json_db.py +13 -0
- arpakitlib/_arpakit_project_template_v1/command/reinit_sqlalchemy_db.py +13 -0
- arpakitlib/_arpakit_project_template_v1/command/remove_operations.py +13 -0
- arpakitlib/_arpakit_project_template_v1/command/remove_story_logs.py +16 -0
- arpakitlib/_arpakit_project_template_v1/command/rm_all_records_in_json_db.py +13 -0
- arpakitlib/{_arpakit_project_template/src/core/_show_settings.py → _arpakit_project_template_v1/command/show_settings.py} +3 -3
- arpakitlib/{_arpakit_project_template/src/api/_start_api_with_reload.py → _arpakit_project_template_v1/command/start_api_with_reload.py} +5 -5
- arpakitlib/{_arpakit_project_template/src/api/_start_api_without_reload.py → _arpakit_project_template_v1/command/start_api_without_reload.py} +5 -5
- arpakitlib/_arpakit_project_template_v1/command/start_async_operation_executor_worker.py +14 -0
- arpakitlib/_arpakit_project_template_v1/command/start_async_scheduled_operation_creator_worker.py +14 -0
- arpakitlib/_arpakit_project_template_v1/command/start_sync_operation_executor_worker.py +15 -0
- arpakitlib/_arpakit_project_template_v1/command/start_sync_operation_executor_workers.py +22 -0
- arpakitlib/_arpakit_project_template_v1/command/start_sync_scheduled_operation_creator_worker.py +12 -0
- arpakitlib/_arpakit_project_template_v1/core/cache_file_storage_in_dir.py +21 -0
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/core/const.py +2 -9
- arpakitlib/_arpakit_project_template_v1/core/dump_file_storage_in_dir.py +21 -0
- arpakitlib/_arpakit_project_template_v1/core/media_file_storage_in_dir.py +21 -0
- arpakitlib/_arpakit_project_template_v1/core/settings.py +193 -0
- arpakitlib/_arpakit_project_template_v1/core/util.py +29 -0
- arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/example.env +10 -5
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/json_db/util.py +2 -2
- arpakitlib/_arpakit_project_template_v1/operation_execution/operation_executor_worker.py +256 -0
- arpakitlib/_arpakit_project_template_v1/operation_execution/scheduled_operation_creator_worker.py +106 -0
- arpakitlib/_arpakit_project_template_v1/operation_execution/scheduled_operations.py +49 -0
- arpakitlib/_arpakit_project_template_v1/operation_execution/util.py +29 -0
- arpakitlib/_arpakit_project_template_v1/resource/static/openapi-favicon.png +0 -0
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/index.html +19 -0
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/swagger-ui-bundle.js +2 -0
- arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui-es-bundle-core.js +1 -1
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/swagger-ui-es-bundle-core.js.map +1 -0
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/swagger-ui-es-bundle.js +2 -0
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/swagger-ui-standalone-preset.js +2 -0
- arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui.js +1 -1
- arpakitlib/_arpakit_project_template_v1/resource/static/swagger-ui/swagger-ui.js.map +1 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_1.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_2.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_3.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_4.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_5.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_6.py +14 -0
- arpakitlib/_arpakit_project_template_v1/sandbox/sandbox_7.py +14 -0
- arpakitlib/{_arpakit_project_template/src/sqlalchemy_db/util.py → _arpakit_project_template_v1/sqlalchemy_db/sqlalchemy_db.py} +3 -11
- arpakitlib/_arpakit_project_template_v1/sqlalchemy_db/sqlalchemy_model.py +129 -0
- arpakitlib/_arpakit_project_template_v1/sqlalchemy_db/util.py +28 -0
- arpakitlib/{_arpakit_project_template/src/sandbox/sandbox_3.py → _arpakit_project_template_v1/test_data/make_test_data_1.py} +8 -3
- arpakitlib/{_arpakit_project_template/src/sandbox/sandbox_4.py → _arpakit_project_template_v1/test_data/make_test_data_2.py} +8 -3
- arpakitlib/{_arpakit_project_template/src/sandbox/sandbox_1.py → _arpakit_project_template_v1/test_data/make_test_data_3.py} +8 -3
- arpakitlib/{_arpakit_project_template/src/sandbox/sandbox_2.py → _arpakit_project_template_v1/test_data/make_test_data_4.py} +8 -3
- arpakitlib/_arpakit_project_template_v1/test_data/make_test_data_5.py +22 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/blank/blank.py +5 -0
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/blank/util.py +1 -1
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/const.py +6 -3
- arpakitlib/_arpakit_project_template_v1/tg_bot/event.py +51 -0
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/filter/not_prod_mode.py +1 -1
- arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/filter/prod_mode.py +1 -1
- arpakitlib/_arpakit_project_template_v1/tg_bot/middleware/init_user.py +24 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/middleware/middleware.py +12 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/router/arpakitlib_.py +10 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/router/error.py +15 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/router/healthcheck.py +10 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/router/main_router.py +14 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/start_tg_bot.py +34 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/tg_bot.py +24 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/tg_bot_dispatcher.py +19 -0
- arpakitlib/_arpakit_project_template_v1/tg_bot/transmitted_tg_data.py +58 -0
- arpakitlib/_arpakit_project_template_v1/util/read_arpakitlib_project_template_file.py +17 -0
- arpakitlib/ar_aiogram_util.py +41 -52
- arpakitlib/ar_arpakit_project_template_util.py +8 -11
- arpakitlib/ar_arpakitlib_cli_util.py +14 -5
- arpakitlib/ar_base_worker_util.py +35 -17
- arpakitlib/ar_class_util.py +11 -0
- arpakitlib/ar_func_util.py +19 -29
- arpakitlib/ar_http_request_util.py +10 -2
- arpakitlib/ar_need_type_util.py +3 -0
- arpakitlib/ar_rat_func_util.py +1 -1
- arpakitlib/ar_retry_func_util.py +4 -4
- arpakitlib/ar_schedule_uust_api_client_util.py +1 -1
- arpakitlib/ar_settings_util.py +3 -204
- arpakitlib/ar_sqladmin_util.py +7 -102
- arpakitlib/ar_sqlalchemy_util.py +65 -13
- arpakitlib/ar_type_util.py +0 -2
- {arpakitlib-1.7.256.dist-info → arpakitlib-1.8.0.dist-info}/METADATA +7 -6
- arpakitlib-1.8.0.dist-info/RECORD +251 -0
- {arpakitlib-1.7.256.dist-info → arpakitlib-1.8.0.dist-info}/WHEEL +1 -1
- arpakitlib/_arpakit_project_template/ARPAKITLIB +0 -1
- arpakitlib/_arpakit_project_template/manage/docker_ps.sh +0 -2
- arpakitlib/_arpakit_project_template/manage/git_branch.sh +0 -2
- arpakitlib/_arpakit_project_template/manage/poetry_add_plugin_export.sh +0 -2
- arpakitlib/_arpakit_project_template/manage/poetry_config_virtualenvs_in_project_true.sh +0 -2
- arpakitlib/_arpakit_project_template/manage/poetry_self_add_plugin_export.sh +0 -2
- arpakitlib/_arpakit_project_template/src/admin1/model_view.py +0 -1
- arpakitlib/_arpakit_project_template/src/api/asgi.py +0 -3
- arpakitlib/_arpakit_project_template/src/api/auth.py +0 -53
- arpakitlib/_arpakit_project_template/src/api/const.py +0 -13
- arpakitlib/_arpakit_project_template/src/api/create_api_app.py +0 -43
- arpakitlib/_arpakit_project_template/src/api/create_handle_exception_.py +0 -59
- arpakitlib/_arpakit_project_template/src/api/event.py +0 -83
- arpakitlib/_arpakit_project_template/src/api/router/v1/get_api_error_info.py +0 -27
- arpakitlib/_arpakit_project_template/src/api/router/v1/main_router.py +0 -15
- arpakitlib/_arpakit_project_template/src/api/schema/v1/in_.py +0 -1
- arpakitlib/_arpakit_project_template/src/api/schema/v1/out.py +0 -1
- arpakitlib/_arpakit_project_template/src/api/transmitted_api_data.py +0 -7
- arpakitlib/_arpakit_project_template/src/api/util.py +0 -44
- arpakitlib/_arpakit_project_template/src/core/settings.py +0 -21
- arpakitlib/_arpakit_project_template/src/core/util.py +0 -61
- arpakitlib/_arpakit_project_template/src/json_db/_drop_json_db.py +0 -13
- arpakitlib/_arpakit_project_template/src/json_db/_init_json_db.py +0 -11
- arpakitlib/_arpakit_project_template/src/json_db/_reinit_json_db.py +0 -13
- arpakitlib/_arpakit_project_template/src/json_db/_rm_all_records_in_json_db.py +0 -13
- arpakitlib/_arpakit_project_template/src/just_script/example.py +0 -16
- arpakitlib/_arpakit_project_template/src/operation_execution/_start_operation_executor_worker.py +0 -17
- arpakitlib/_arpakit_project_template/src/operation_execution/_start_scheduled_operation_creator_worker.py +0 -17
- arpakitlib/_arpakit_project_template/src/operation_execution/const.py +0 -9
- arpakitlib/_arpakit_project_template/src/operation_execution/operation_executor.py +0 -16
- arpakitlib/_arpakit_project_template/src/operation_execution/scheduled_operations.py +0 -29
- arpakitlib/_arpakit_project_template/src/operation_execution/util.py +0 -1
- arpakitlib/_arpakit_project_template/src/sandbox/sandbox_5.py +0 -17
- arpakitlib/_arpakit_project_template/src/sandbox/sandbox_6.py +0 -17
- arpakitlib/_arpakit_project_template/src/sandbox/sandbox_7.py +0 -17
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_check_conn_sqlalchemy_db.py +0 -11
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_drop_sqlalchemy_db.py +0 -13
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_init_sqlalchemy_db.py +0 -11
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_reinit_sqlalchemy_db.py +0 -13
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_remove_operations.py +0 -15
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/_remove_story_logs.py +0 -16
- arpakitlib/_arpakit_project_template/src/sqlalchemy_db/sqlalchemy_model.py +0 -13
- arpakitlib/_arpakit_project_template/src/test_data/make_test_data_1.py +0 -8
- arpakitlib/_arpakit_project_template/src/test_data/make_test_data_2.py +0 -8
- arpakitlib/_arpakit_project_template/src/test_data/make_test_data_3.py +0 -8
- arpakitlib/_arpakit_project_template/src/test_data/make_test_data_4.py +0 -8
- arpakitlib/_arpakit_project_template/src/test_data/make_test_data_5.py +0 -8
- arpakitlib/_arpakit_project_template/src/tg_bot/blank/blank.py +0 -10
- arpakitlib/_arpakit_project_template/src/tg_bot/event.py +0 -39
- arpakitlib/_arpakit_project_template/src/tg_bot/handler/cmd_healthcheck.py +0 -0
- arpakitlib/_arpakit_project_template/src/tg_bot/router/error.py +0 -3
- arpakitlib/_arpakit_project_template/src/tg_bot/router/router.py +0 -7
- arpakitlib/_arpakit_project_template/src/tg_bot/start_tg_bot.py +0 -11
- arpakitlib/_arpakit_project_template/src/tg_bot/transmitted_tg_data.py +0 -6
- arpakitlib/_arpakit_project_template/src/tg_bot/util.py +0 -44
- arpakitlib/ar_api_key_util.py +0 -21
- arpakitlib/ar_fastapi_static/healthcheck +0 -1
- arpakitlib/ar_fastapi_static/swagger-ui/index.html +0 -19
- arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui-bundle.js +0 -2
- arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui-es-bundle-core.js.map +0 -1
- arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui-es-bundle.js +0 -2
- arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui-standalone-preset.js +0 -2
- arpakitlib/ar_fastapi_static/swagger-ui/swagger-ui.js.map +0 -1
- arpakitlib/ar_fastapi_util.py +0 -862
- arpakitlib/ar_operation_execution_util.py +0 -504
- arpakitlib/ar_sqlalchemy_model_util.py +0 -183
- arpakitlib-1.7.256.dist-info/RECORD +0 -236
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/.gitignore +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/.python-version +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/LICENSE +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/additional_model}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/additional_model/additional_model.py +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note → _arpakit_project_template_v1/admin1}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/alembic/README +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/alembic/script.py.mako +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/alembic.ini +0 -0
- /arpakitlib/{_arpakit_project_template/resource → _arpakit_project_template_v1/api}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/resource/static → _arpakit_project_template_v1/api/router}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1/api/router/v1}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/additional_model → _arpakit_project_template_v1/api/schema}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/admin1 → _arpakit_project_template_v1/api/schema/common}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/api → _arpakit_project_template_v1/api/schema/v1}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note/note_1.txt → _arpakit_project_template_v1/api/util.py} +0 -0
- /arpakitlib/{_arpakit_project_template/src/api/router → _arpakit_project_template_v1/business_service}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/api/router/v1 → _arpakit_project_template_v1/command}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/alembic_upgrade_head .sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/docker_ps_a.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/docker_rm_postgres.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/docker_run_postgres.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/docker_start_postgres.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/docker_stop_postgres.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_commit.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_push_arpakit_company_github_1.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_push_arpakit_company_gitlab_1.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_push_arpakit_github_1.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_push_arpakit_gitlab_1.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage/git_remote_v.sh → _arpakit_project_template_v1/command/git_remote.sh} +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_set_arpakit_company_origin.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_set_arpakit_origin.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/git_status.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_check.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_clear_cache.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_config.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_install.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_lock.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_remove_and_add_arpakitlib.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_show.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_show_arpakitlib.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_update.sh +0 -0
- /arpakitlib/{_arpakit_project_template/manage → _arpakit_project_template_v1/command}/poetry_update_arpakitlib.sh +0 -0
- /arpakitlib/{_arpakit_project_template/src/api/schema → _arpakit_project_template_v1/core}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/api/schema/v1 → _arpakit_project_template_v1/json_db}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/json_db/json_db.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/business_service → _arpakit_project_template_v1/note}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note/note_2.txt → _arpakit_project_template_v1/note/note_1.txt} +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note/note_3.txt → _arpakit_project_template_v1/note/note_2.txt} +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note/note_4.txt → _arpakit_project_template_v1/note/note_3.txt} +0 -0
- /arpakitlib/{_arpakit_project_template/manage/note/note_5.txt → _arpakit_project_template_v1/note/note_4.txt} +0 -0
- /arpakitlib/{_arpakit_project_template/src/core/__init__.py → _arpakit_project_template_v1/note/note_5.txt} +0 -0
- /arpakitlib/{_arpakit_project_template/src/json_db → _arpakit_project_template_v1/operation_execution}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/just_script/__init__.py → _arpakit_project_template_v1/operation_execution/const.py} +0 -0
- /arpakitlib/{_arpakit_project_template/src/operation_execution → _arpakit_project_template_v1/resource}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/sandbox → _arpakit_project_template_v1/resource/static}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/resource/static/healthcheck +0 -0
- /arpakitlib/{_arpakit_project_template → _arpakit_project_template_v1}/resource/static/helloworld +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/redoc/redoc.standalone.js +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/favicon-16x16.png +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/favicon-32x32.png +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/index.css +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/oauth2-redirect.html +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-initializer.js +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui-bundle.js.map +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui-es-bundle.js.map +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui-standalone-preset.js.map +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui.css +0 -0
- /arpakitlib/{ar_fastapi_static → _arpakit_project_template_v1/resource/static}/swagger-ui/swagger-ui.css.map +0 -0
- /arpakitlib/{_arpakit_project_template/src/sqlalchemy_db → _arpakit_project_template_v1/sandbox}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/test_data → _arpakit_project_template_v1/sqlalchemy_db}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/sqlalchemy_db/const.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/tg_bot → _arpakit_project_template_v1/test_data}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/tg_bot/blank → _arpakit_project_template_v1/tg_bot}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/tg_bot/filter → _arpakit_project_template_v1/tg_bot/blank}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/tg_bot/handler → _arpakit_project_template_v1/tg_bot/filter}/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/inline_/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/inline_/callback.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/inline_/common.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/static_/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/kb/static_/common.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/middleware/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/tg_bot/router/__init__.py +0 -0
- /arpakitlib/{_arpakit_project_template/src/tg_bot/handler/cmd_arpakitlib.py → _arpakit_project_template_v1/tg_bot/util.py} +0 -0
- /arpakitlib/{_arpakit_project_template/src → _arpakit_project_template_v1}/util/__init__.py +0 -0
- {arpakitlib-1.7.256.dist-info → arpakitlib-1.8.0.dist-info}/LICENSE +0 -0
- {arpakitlib-1.7.256.dist-info → arpakitlib-1.8.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,193 @@
|
|
1
|
+
import os
|
2
|
+
from functools import lru_cache
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
import pytz
|
6
|
+
from pydantic import field_validator
|
7
|
+
from pydantic_core.core_schema import ValidationInfo
|
8
|
+
|
9
|
+
from arpakitlib.ar_enumeration_util import Enumeration
|
10
|
+
from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
|
11
|
+
from arpakitlib.ar_settings_util import SimpleSettings
|
12
|
+
from arpakitlib.ar_sqlalchemy_util import generate_sqlalchemy_url
|
13
|
+
from core.const import ProjectPaths
|
14
|
+
|
15
|
+
|
16
|
+
class ModeTypes(Enumeration):
|
17
|
+
not_prod: str = "not_prod"
|
18
|
+
prod: str = "prod"
|
19
|
+
|
20
|
+
|
21
|
+
class Settings(SimpleSettings):
|
22
|
+
mode_type: str = ModeTypes.not_prod
|
23
|
+
|
24
|
+
@field_validator("mode_type")
|
25
|
+
@classmethod
|
26
|
+
def validate_mode_type(cls, v: Any, validation_info: ValidationInfo, **kwargs):
|
27
|
+
if v is None:
|
28
|
+
v = ModeTypes.not_prod
|
29
|
+
ModeTypes.parse_and_validate_values(v.lower().strip())
|
30
|
+
return v
|
31
|
+
|
32
|
+
@property
|
33
|
+
def is_mode_type_not_prod(self) -> bool:
|
34
|
+
return self.mode_type == ModeTypes.not_prod
|
35
|
+
|
36
|
+
def raise_if_mode_type_not_prod(self):
|
37
|
+
if self.is_mode_type_not_prod:
|
38
|
+
raise ValueError(f"mode type = {self.mode_type}")
|
39
|
+
|
40
|
+
@property
|
41
|
+
def is_mode_type_prod(self) -> bool:
|
42
|
+
return self.mode_type == ModeTypes.prod
|
43
|
+
|
44
|
+
def raise_if_mode_type_prod(self):
|
45
|
+
if self.is_mode_type_prod:
|
46
|
+
raise ValueError(f"mode type = {self.mode_type}")
|
47
|
+
|
48
|
+
project_name: str | None = "arpakitlib"
|
49
|
+
|
50
|
+
sqlalchemy_db_user: str | None = project_name
|
51
|
+
|
52
|
+
sqlalchemy_db_password: str | None = project_name
|
53
|
+
|
54
|
+
sqlalchemy_db_host: str | None = "127.0.0.1"
|
55
|
+
|
56
|
+
sqlalchemy_db_port: int | None = 5432
|
57
|
+
|
58
|
+
sqlalchemy_db_database: str | None = project_name
|
59
|
+
|
60
|
+
sqlalchemy_sync_db_url: str | None = None
|
61
|
+
|
62
|
+
@field_validator("sqlalchemy_sync_db_url", mode="after")
|
63
|
+
def validate_sqlalchemy_sync_db_url(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> str | None:
|
64
|
+
if v is not None:
|
65
|
+
return v
|
66
|
+
|
67
|
+
return generate_sqlalchemy_url(
|
68
|
+
base="postgresql",
|
69
|
+
user=validation_info.data.get("sqlalchemy_db_user"),
|
70
|
+
password=validation_info.data.get("sqlalchemy_db_password"),
|
71
|
+
host=validation_info.data.get("sqlalchemy_db_host"),
|
72
|
+
port=validation_info.data.get("sqlalchemy_db_port"),
|
73
|
+
database=validation_info.data.get("sqlalchemy_db_database")
|
74
|
+
)
|
75
|
+
|
76
|
+
sqlalchemy_async_db_url: str | None = None
|
77
|
+
|
78
|
+
@field_validator("sqlalchemy_async_db_url", mode="after")
|
79
|
+
def validate_sqlalchemy_async_db_url(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> str | None:
|
80
|
+
if v is not None:
|
81
|
+
return v
|
82
|
+
|
83
|
+
return generate_sqlalchemy_url(
|
84
|
+
base="postgresql+asyncpg",
|
85
|
+
user=validation_info.data.get("sqlalchemy_db_user"),
|
86
|
+
password=validation_info.data.get("sqlalchemy_db_password"),
|
87
|
+
host=validation_info.data.get("sqlalchemy_db_host"),
|
88
|
+
port=validation_info.data.get("sqlalchemy_db_port"),
|
89
|
+
database=validation_info.data.get("sqlalchemy_db_database")
|
90
|
+
)
|
91
|
+
|
92
|
+
@property
|
93
|
+
def is_any_sql_db_url_set(self) -> bool:
|
94
|
+
if self.sqlalchemy_sync_db_url is not None:
|
95
|
+
return True
|
96
|
+
if self.sqlalchemy_async_db_url is not None:
|
97
|
+
return True
|
98
|
+
return False
|
99
|
+
|
100
|
+
sqlalchemy_db_echo: bool = False
|
101
|
+
|
102
|
+
api_port: int | None = 50519
|
103
|
+
|
104
|
+
api_init_sqlalchemy_db: bool = False
|
105
|
+
|
106
|
+
api_init_json_db: bool = False
|
107
|
+
|
108
|
+
api_correct_api_keys: list[str] | None = "1"
|
109
|
+
|
110
|
+
@field_validator("api_correct_api_keys", mode="before")
|
111
|
+
def validate_api_correct_api_keys(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> list[str] | None:
|
112
|
+
if isinstance(v, str):
|
113
|
+
v = [v]
|
114
|
+
if isinstance(v, int):
|
115
|
+
v = [str(v)]
|
116
|
+
if isinstance(v, list):
|
117
|
+
for i, v_ in enumerate(v):
|
118
|
+
if isinstance(v_, int):
|
119
|
+
v[i] = str(v_)
|
120
|
+
return v
|
121
|
+
|
122
|
+
api_correct_tokens: list[str] | None = "1"
|
123
|
+
|
124
|
+
@field_validator("api_correct_tokens", mode="before")
|
125
|
+
def validate_api_correct_tokens(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> list[str] | None:
|
126
|
+
if isinstance(v, str):
|
127
|
+
v = [v]
|
128
|
+
if isinstance(v, int):
|
129
|
+
v = [str(v)]
|
130
|
+
if isinstance(v, list):
|
131
|
+
for i, v_ in enumerate(v):
|
132
|
+
if isinstance(v_, int):
|
133
|
+
v[i] = str(v_)
|
134
|
+
return v
|
135
|
+
|
136
|
+
api_enable_admin1: bool = True
|
137
|
+
|
138
|
+
api_start_operation_executor_worker: bool = False
|
139
|
+
|
140
|
+
api_start_scheduled_operation_creator_worker: bool = False
|
141
|
+
|
142
|
+
api_story_log__api_func_before_in_exception_handler: bool = True
|
143
|
+
|
144
|
+
admin1_secret_key: str | None = "85a9583cb91c4de7a78d7eb1e5306a04418c9c43014c447ea8ec8dd5deb4cf71"
|
145
|
+
|
146
|
+
tg_bot_token: str | None = None
|
147
|
+
|
148
|
+
tg_bot_proxy_url: str | None = None
|
149
|
+
|
150
|
+
tg_bot_init_sqlalchemy_db: bool = False
|
151
|
+
|
152
|
+
tg_bot_init_json_db: bool = False
|
153
|
+
|
154
|
+
tg_bot_webhook_server_hostname: str | None = "127.0.0.1"
|
155
|
+
|
156
|
+
tg_bot_webhook_server_port: int | None = None
|
157
|
+
|
158
|
+
tg_bot_webhook_path: str | None = "/tg_bot_webhook"
|
159
|
+
|
160
|
+
tg_bot_webhook_secret: str | None = "09780c63-22b5-44e2-9b72-f0cf651f7a9a"
|
161
|
+
|
162
|
+
tg_bot_webhook_url: str | None = None
|
163
|
+
|
164
|
+
tg_bot_webhook_enabled: bool = False
|
165
|
+
|
166
|
+
var_dirpath: str | None = os.path.join(ProjectPaths.base_dirpath, "var")
|
167
|
+
|
168
|
+
log_filepath: str | None = os.path.join(var_dirpath, "story.log")
|
169
|
+
|
170
|
+
cache_dirpath: str | None = os.path.join(var_dirpath, "cache")
|
171
|
+
|
172
|
+
media_dirpath: str | None = os.path.join(var_dirpath, "media")
|
173
|
+
|
174
|
+
dump_dirpath: str | None = os.path.join(var_dirpath, "dump")
|
175
|
+
|
176
|
+
json_db_dirpath: str | None = os.path.join(var_dirpath, f"{project_name}_json_db")
|
177
|
+
|
178
|
+
local_timezone: str | None = None
|
179
|
+
|
180
|
+
@property
|
181
|
+
def local_timezone_as_pytz(self) -> Any:
|
182
|
+
return pytz.timezone(self.local_timezone)
|
183
|
+
|
184
|
+
|
185
|
+
@lru_cache()
|
186
|
+
def get_cached_settings() -> Settings:
|
187
|
+
if os.path.exists(ProjectPaths.env_filepath):
|
188
|
+
return Settings(_env_file=ProjectPaths.env_filepath, _env_file_encoding="utf-8")
|
189
|
+
return Settings()
|
190
|
+
|
191
|
+
|
192
|
+
if __name__ == '__main__':
|
193
|
+
print(safely_transfer_obj_to_json_str(get_cached_settings().model_dump(mode="json")))
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import asyncio
|
2
|
+
from datetime import datetime
|
3
|
+
|
4
|
+
from arpakitlib.ar_datetime_util import now_dt
|
5
|
+
from arpakitlib.ar_logging_util import setup_normal_logging
|
6
|
+
from arpakitlib.ar_type_util import raise_if_none
|
7
|
+
from core.settings import get_cached_settings
|
8
|
+
|
9
|
+
|
10
|
+
def setup_logging():
|
11
|
+
setup_normal_logging(log_filepath=get_cached_settings().log_filepath)
|
12
|
+
|
13
|
+
|
14
|
+
def now_local_dt() -> datetime:
|
15
|
+
raise_if_none(get_cached_settings().local_timezone_as_pytz)
|
16
|
+
return now_dt(tz=get_cached_settings().local_timezone_as_pytz)
|
17
|
+
|
18
|
+
|
19
|
+
def __example():
|
20
|
+
pass
|
21
|
+
|
22
|
+
|
23
|
+
async def __async_example():
|
24
|
+
pass
|
25
|
+
|
26
|
+
|
27
|
+
if __name__ == '__main__':
|
28
|
+
__example()
|
29
|
+
asyncio.run(__async_example())
|
@@ -11,22 +11,27 @@
|
|
11
11
|
# api_port=
|
12
12
|
# api_init_sqlalchemy_db=
|
13
13
|
# api_init_json_db=
|
14
|
-
#
|
15
|
-
#
|
16
|
-
# api_correct_api_key=
|
17
|
-
# api_correct_token=
|
14
|
+
# api_correct_api_keys=
|
15
|
+
# api_correct_tokens=
|
18
16
|
# api_enable_admin1=
|
19
17
|
# api_start_operation_executor_worker=
|
20
18
|
# api_start_scheduled_operation_creator_worker=
|
19
|
+
# api_story_log__api_func_before_in_exception_handler=
|
21
20
|
# admin1_secret_key=
|
22
21
|
# tg_bot_token=
|
23
22
|
# tg_bot_proxy_url=
|
24
23
|
# tg_bot_init_sqlalchemy_db=
|
25
24
|
# tg_bot_init_json_db=
|
25
|
+
# tg_bot_webhook_server_hostname=
|
26
|
+
# tg_bot_webhook_server_port=
|
27
|
+
# tg_bot_webhook_path=
|
28
|
+
# tg_bot_webhook_secret=
|
29
|
+
# tg_bot_webhook_url=
|
30
|
+
# tg_bot_webhook_enabled=
|
26
31
|
# var_dirpath=
|
27
32
|
# log_filepath=
|
28
33
|
# cache_dirpath=
|
29
34
|
# media_dirpath=
|
30
35
|
# dump_dirpath=
|
31
|
-
# local_timezone=
|
32
36
|
# json_db_dirpath=
|
37
|
+
# local_timezone=
|
@@ -0,0 +1,256 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import inspect
|
4
|
+
from datetime import timedelta
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
import sqlalchemy
|
8
|
+
from sqlalchemy import asc
|
9
|
+
|
10
|
+
from arpakitlib.ar_base_worker_util import BaseWorker
|
11
|
+
from arpakitlib.ar_datetime_util import now_utc_dt
|
12
|
+
from arpakitlib.ar_dict_util import combine_dicts
|
13
|
+
from arpakitlib.ar_exception_util import exception_to_traceback_str
|
14
|
+
from arpakitlib.ar_sqlalchemy_util import SQLAlchemyDb
|
15
|
+
from arpakitlib.ar_type_util import raise_for_type
|
16
|
+
from sqlalchemy_db.sqlalchemy_db import get_cached_sqlalchemy_db
|
17
|
+
from sqlalchemy_db.sqlalchemy_model import OperationDBM, StoryLogDBM
|
18
|
+
|
19
|
+
|
20
|
+
class OperationExecutorWorker(BaseWorker):
|
21
|
+
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
*,
|
25
|
+
sqlalchemy_db: SQLAlchemyDb,
|
26
|
+
filter_operation_types: str | list[str] | None = None,
|
27
|
+
startup_funcs: list[Any] | None = None
|
28
|
+
):
|
29
|
+
super().__init__(
|
30
|
+
timeout_after_run=timedelta(seconds=0.1),
|
31
|
+
timeout_after_error_in_run=timedelta(seconds=0.1),
|
32
|
+
startup_funcs=startup_funcs,
|
33
|
+
)
|
34
|
+
|
35
|
+
raise_for_type(sqlalchemy_db, SQLAlchemyDb)
|
36
|
+
self.sqlalchemy_db = sqlalchemy_db
|
37
|
+
|
38
|
+
if isinstance(filter_operation_types, str):
|
39
|
+
filter_operation_types = [filter_operation_types]
|
40
|
+
self.filter_operation_types = filter_operation_types
|
41
|
+
|
42
|
+
def sync_execute_operation(self, operation_dbm: OperationDBM):
|
43
|
+
if operation_dbm.type == OperationDBM.Types.healthcheck_:
|
44
|
+
self._logger.info(f"healthcheck {now_utc_dt()}")
|
45
|
+
elif operation_dbm.type == OperationDBM.Types.raise_fake_error_:
|
46
|
+
self._logger.error(f"{OperationDBM.Types.raise_fake_error_}")
|
47
|
+
raise Exception(f"{OperationDBM.Types.raise_fake_error_}")
|
48
|
+
# ...
|
49
|
+
|
50
|
+
async def async_execute_operation(self, *, operation_dbm: OperationDBM):
|
51
|
+
if operation_dbm.type == OperationDBM.Types.healthcheck_:
|
52
|
+
self._logger.info(f"healthcheck {now_utc_dt()}")
|
53
|
+
elif operation_dbm.type == OperationDBM.Types.raise_fake_error_:
|
54
|
+
self._logger.error(f"{OperationDBM.Types.raise_fake_error_}")
|
55
|
+
raise Exception(f"{OperationDBM.Types.raise_fake_error_}")
|
56
|
+
# ...
|
57
|
+
|
58
|
+
def sync_run(self):
|
59
|
+
# 1
|
60
|
+
with self.sqlalchemy_db.new_session() as sync_session:
|
61
|
+
query = (
|
62
|
+
sync_session
|
63
|
+
.query(OperationDBM)
|
64
|
+
.filter(OperationDBM.status == OperationDBM.Statuses.waiting_for_execution)
|
65
|
+
)
|
66
|
+
if self.filter_operation_types is not None:
|
67
|
+
query = query.filter(OperationDBM.type.in_(self.filter_operation_types))
|
68
|
+
query = query.with_for_update()
|
69
|
+
query = query.order_by(asc(OperationDBM.creation_dt))
|
70
|
+
operation_dbm: OperationDBM | None = query.first()
|
71
|
+
if operation_dbm is None:
|
72
|
+
return
|
73
|
+
operation_dbm.execution_start_dt = now_utc_dt()
|
74
|
+
operation_dbm.status = OperationDBM.Statuses.executing
|
75
|
+
operation_dbm.output_data = combine_dicts(
|
76
|
+
operation_dbm.output_data,
|
77
|
+
{
|
78
|
+
self.worker_fullname: True,
|
79
|
+
f"{inspect.currentframe().f_code.co_name}": True
|
80
|
+
}
|
81
|
+
)
|
82
|
+
sync_session.commit()
|
83
|
+
sync_session.refresh(operation_dbm)
|
84
|
+
|
85
|
+
# 2
|
86
|
+
self._logger.info(
|
87
|
+
f"start execute_operation"
|
88
|
+
f", operation_id={operation_dbm.id}"
|
89
|
+
f", operation_type={operation_dbm.type})"
|
90
|
+
f", worker_fullname={self.worker_fullname}"
|
91
|
+
)
|
92
|
+
exception_in_execute_operation: Exception | None = None
|
93
|
+
try:
|
94
|
+
self.sync_execute_operation(operation_dbm=operation_dbm)
|
95
|
+
except Exception as exception:
|
96
|
+
self._logger.exception(
|
97
|
+
f"exception in execute_operation"
|
98
|
+
f", operation_id={operation_dbm.id}"
|
99
|
+
f", operation_type={operation_dbm.type}"
|
100
|
+
f", worker_fullname={self.worker_fullname}",
|
101
|
+
)
|
102
|
+
exception_in_execute_operation = exception
|
103
|
+
|
104
|
+
# 3
|
105
|
+
with self.sqlalchemy_db.new_session() as sync_session:
|
106
|
+
operation_dbm: OperationDBM = (
|
107
|
+
sync_session.query(OperationDBM).with_for_update().filter(OperationDBM.id == operation_dbm.id).one()
|
108
|
+
)
|
109
|
+
operation_dbm.execution_finish_dt = now_utc_dt()
|
110
|
+
if exception_in_execute_operation is not None:
|
111
|
+
operation_dbm.status = OperationDBM.Statuses.executed_with_error
|
112
|
+
operation_dbm.error_data = combine_dicts(
|
113
|
+
operation_dbm.error_data,
|
114
|
+
{
|
115
|
+
"exception_in_execute_operation": str(exception_in_execute_operation),
|
116
|
+
"traceback_str_in_execute_operation": exception_to_traceback_str(
|
117
|
+
exception=exception_in_execute_operation
|
118
|
+
),
|
119
|
+
}
|
120
|
+
)
|
121
|
+
else:
|
122
|
+
operation_dbm.status = OperationDBM.Statuses.executed_without_error
|
123
|
+
sync_session.commit()
|
124
|
+
sync_session.refresh(operation_dbm)
|
125
|
+
self._logger.info(
|
126
|
+
f"finish execute_operation"
|
127
|
+
f", operation_id={operation_dbm.id}"
|
128
|
+
f", operation_type={operation_dbm.type}"
|
129
|
+
f", worker_fullname={self.worker_fullname}"
|
130
|
+
)
|
131
|
+
|
132
|
+
# 4
|
133
|
+
if exception_in_execute_operation is not None:
|
134
|
+
with self.sqlalchemy_db.new_session() as sync_session:
|
135
|
+
story_log_dbm = StoryLogDBM(
|
136
|
+
level=StoryLogDBM.Levels.error,
|
137
|
+
type=StoryLogDBM.Types.error_in_execute_operation,
|
138
|
+
title=(
|
139
|
+
f"error in execute_operation"
|
140
|
+
f", operation_id={operation_dbm.id}"
|
141
|
+
f", operation_type={operation_dbm.type}"
|
142
|
+
),
|
143
|
+
data={
|
144
|
+
"operation_id": operation_dbm.id,
|
145
|
+
"operation_type": operation_dbm.type,
|
146
|
+
}
|
147
|
+
)
|
148
|
+
sync_session.add(story_log_dbm)
|
149
|
+
sync_session.commit()
|
150
|
+
sync_session.refresh(story_log_dbm)
|
151
|
+
|
152
|
+
async def async_run(self):
|
153
|
+
# 1
|
154
|
+
async with self.sqlalchemy_db.new_async_session() as async_session:
|
155
|
+
query = (
|
156
|
+
sqlalchemy.select(OperationDBM)
|
157
|
+
.filter(OperationDBM.status == OperationDBM.Statuses.waiting_for_execution)
|
158
|
+
)
|
159
|
+
if self.filter_operation_types is not None:
|
160
|
+
query = query.filter(OperationDBM.type.in_(self.filter_operation_types))
|
161
|
+
query = query.order_by(asc(OperationDBM.creation_dt)).with_for_update()
|
162
|
+
|
163
|
+
result = await async_session.execute(query)
|
164
|
+
operation_dbm = result.scalars().first()
|
165
|
+
if operation_dbm is None:
|
166
|
+
return
|
167
|
+
|
168
|
+
operation_dbm.execution_start_dt = now_utc_dt()
|
169
|
+
operation_dbm.status = OperationDBM.Statuses.executing
|
170
|
+
operation_dbm.output_data = combine_dicts(
|
171
|
+
operation_dbm.output_data,
|
172
|
+
{
|
173
|
+
self.worker_fullname: True,
|
174
|
+
f"{inspect.currentframe().f_code.co_name}": True
|
175
|
+
}
|
176
|
+
)
|
177
|
+
await async_session.commit()
|
178
|
+
await async_session.refresh(operation_dbm)
|
179
|
+
|
180
|
+
# 2
|
181
|
+
self._logger.info(
|
182
|
+
f"start execute_operation"
|
183
|
+
f", operation_id={operation_dbm.id}"
|
184
|
+
f", operation_type={operation_dbm.type})"
|
185
|
+
f", worker_fullname={self.worker_fullname}"
|
186
|
+
)
|
187
|
+
exception_in_execute_operation = None
|
188
|
+
try:
|
189
|
+
await self.async_execute_operation(operation_dbm=operation_dbm)
|
190
|
+
except Exception as exception:
|
191
|
+
self._logger.exception(
|
192
|
+
f"exception in execute_operation"
|
193
|
+
f", operation_id={operation_dbm.id}"
|
194
|
+
f", operation_type={operation_dbm.type}"
|
195
|
+
f", worker_fullname={self.worker_fullname}",
|
196
|
+
)
|
197
|
+
exception_in_execute_operation = exception
|
198
|
+
|
199
|
+
# 3
|
200
|
+
async with self.sqlalchemy_db.new_async_session() as async_session:
|
201
|
+
result = await async_session.execute(
|
202
|
+
sqlalchemy.select(OperationDBM).filter(OperationDBM.id == operation_dbm.id).with_for_update()
|
203
|
+
)
|
204
|
+
operation_dbm = result.scalars().one()
|
205
|
+
operation_dbm.execution_finish_dt = now_utc_dt()
|
206
|
+
if exception_in_execute_operation is not None:
|
207
|
+
operation_dbm.status = OperationDBM.Statuses.executed_with_error
|
208
|
+
operation_dbm.error_data = combine_dicts(
|
209
|
+
{
|
210
|
+
"exception_in_execute_operation": str(exception_in_execute_operation),
|
211
|
+
"traceback_str_in_execute_operation": exception_to_traceback_str(
|
212
|
+
exception=exception_in_execute_operation
|
213
|
+
)
|
214
|
+
},
|
215
|
+
operation_dbm.error_data
|
216
|
+
)
|
217
|
+
else:
|
218
|
+
operation_dbm.status = OperationDBM.Statuses.executed_without_error
|
219
|
+
await async_session.commit()
|
220
|
+
await async_session.refresh(operation_dbm)
|
221
|
+
self._logger.info(
|
222
|
+
f"finish execute_operation"
|
223
|
+
f", operation_id={operation_dbm.id}"
|
224
|
+
f", operation_type={operation_dbm.type}"
|
225
|
+
f", worker_fullname={self.worker_fullname}"
|
226
|
+
)
|
227
|
+
|
228
|
+
# 4
|
229
|
+
if exception_in_execute_operation is not None:
|
230
|
+
async with self.sqlalchemy_db.new_async_session() as async_session:
|
231
|
+
story_log_dbm = StoryLogDBM(
|
232
|
+
level=StoryLogDBM.Levels.error,
|
233
|
+
type=StoryLogDBM.Types.error_in_execute_operation,
|
234
|
+
title=(
|
235
|
+
f"error in execute_operation"
|
236
|
+
f", operation_id={operation_dbm.id}"
|
237
|
+
f", operation_type={operation_dbm.type}"
|
238
|
+
),
|
239
|
+
data={
|
240
|
+
"operation_id": operation_dbm.id,
|
241
|
+
"operation_type": operation_dbm.type,
|
242
|
+
}
|
243
|
+
)
|
244
|
+
async_session.add(story_log_dbm)
|
245
|
+
await async_session.commit()
|
246
|
+
await async_session.refresh(story_log_dbm)
|
247
|
+
|
248
|
+
|
249
|
+
def create_operation_executor_worker(
|
250
|
+
*,
|
251
|
+
filter_operation_types: str | list[str] | None = None
|
252
|
+
) -> OperationExecutorWorker:
|
253
|
+
return OperationExecutorWorker(
|
254
|
+
sqlalchemy_db=get_cached_sqlalchemy_db(),
|
255
|
+
filter_operation_types=filter_operation_types
|
256
|
+
)
|
arpakitlib/_arpakit_project_template_v1/operation_execution/scheduled_operation_creator_worker.py
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
from datetime import timedelta
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
from arpakitlib.ar_base_worker_util import BaseWorker
|
5
|
+
from arpakitlib.ar_sleep_util import sync_safe_sleep, async_safe_sleep
|
6
|
+
from arpakitlib.ar_sqlalchemy_util import SQLAlchemyDb
|
7
|
+
from arpakitlib.ar_type_util import raise_for_type
|
8
|
+
from operation_execution.scheduled_operations import ScheduledOperation, get_scheduled_operations
|
9
|
+
from sqlalchemy_db.sqlalchemy_db import get_cached_sqlalchemy_db
|
10
|
+
from sqlalchemy_db.sqlalchemy_model import OperationDBM
|
11
|
+
|
12
|
+
|
13
|
+
class ScheduledOperationCreatorWorker(BaseWorker):
|
14
|
+
def __init__(
|
15
|
+
self,
|
16
|
+
*,
|
17
|
+
sqlalchemy_db: SQLAlchemyDb,
|
18
|
+
scheduled_operations: ScheduledOperation | list[ScheduledOperation] | None = None,
|
19
|
+
startup_funcs: list[Any] | None = None
|
20
|
+
):
|
21
|
+
super().__init__(
|
22
|
+
timeout_after_run=timedelta(seconds=0.1),
|
23
|
+
timeout_after_error_in_run=timedelta(seconds=0.1),
|
24
|
+
startup_funcs=startup_funcs
|
25
|
+
)
|
26
|
+
|
27
|
+
raise_for_type(sqlalchemy_db, SQLAlchemyDb)
|
28
|
+
self.sqlalchemy_db = sqlalchemy_db
|
29
|
+
|
30
|
+
if scheduled_operations is None:
|
31
|
+
scheduled_operations = []
|
32
|
+
if isinstance(scheduled_operations, ScheduledOperation):
|
33
|
+
scheduled_operations = [scheduled_operations]
|
34
|
+
raise_for_type(scheduled_operations, list)
|
35
|
+
self.scheduled_operations = scheduled_operations
|
36
|
+
|
37
|
+
def sync_run(self):
|
38
|
+
timeout = None
|
39
|
+
|
40
|
+
for scheduled_operation in self.scheduled_operations:
|
41
|
+
|
42
|
+
if not scheduled_operation.is_time_func():
|
43
|
+
continue
|
44
|
+
|
45
|
+
with self.sqlalchemy_db.new_session() as session:
|
46
|
+
operation_dbm = OperationDBM(
|
47
|
+
type=scheduled_operation.type,
|
48
|
+
input_data=scheduled_operation.input_data
|
49
|
+
)
|
50
|
+
session.add(operation_dbm)
|
51
|
+
session.commit()
|
52
|
+
session.refresh(operation_dbm)
|
53
|
+
self._logger.info(
|
54
|
+
f"scheduled operation was created"
|
55
|
+
f", operation_id={operation_dbm.id}"
|
56
|
+
f", operation_type={operation_dbm.type}"
|
57
|
+
)
|
58
|
+
|
59
|
+
if scheduled_operation.timeout_after_creation is not None:
|
60
|
+
if timeout is not None:
|
61
|
+
if scheduled_operation.timeout_after_creation > timeout:
|
62
|
+
timeout = scheduled_operation.timeout_after_creation
|
63
|
+
else:
|
64
|
+
timeout = scheduled_operation.timeout_after_creation
|
65
|
+
|
66
|
+
if timeout is not None:
|
67
|
+
sync_safe_sleep(n=timeout)
|
68
|
+
|
69
|
+
async def async_run(self):
|
70
|
+
timeout: timedelta | None = None
|
71
|
+
|
72
|
+
for scheduled_operation in self.scheduled_operations:
|
73
|
+
|
74
|
+
if not scheduled_operation.is_time_func():
|
75
|
+
continue
|
76
|
+
|
77
|
+
async with self.sqlalchemy_db.new_async_session() as async_session:
|
78
|
+
operation_dbm = OperationDBM(
|
79
|
+
type=scheduled_operation.type,
|
80
|
+
input_data=scheduled_operation.input_data
|
81
|
+
)
|
82
|
+
async_session.add(operation_dbm)
|
83
|
+
await async_session.commit()
|
84
|
+
await async_session.refresh(operation_dbm)
|
85
|
+
self._logger.info(
|
86
|
+
f"scheduled operation was created"
|
87
|
+
f", operation_id={operation_dbm.id}"
|
88
|
+
f", operation_type={operation_dbm.type}"
|
89
|
+
)
|
90
|
+
|
91
|
+
if scheduled_operation.timeout_after_creation is not None:
|
92
|
+
if timeout is not None:
|
93
|
+
if scheduled_operation.timeout_after_creation > timeout:
|
94
|
+
timeout = scheduled_operation.timeout_after_creation
|
95
|
+
else:
|
96
|
+
timeout = scheduled_operation.timeout_after_creation
|
97
|
+
|
98
|
+
if timeout is not None:
|
99
|
+
await async_safe_sleep(n=timeout)
|
100
|
+
|
101
|
+
|
102
|
+
def create_scheduled_operation_creator_worker() -> ScheduledOperationCreatorWorker:
|
103
|
+
return ScheduledOperationCreatorWorker(
|
104
|
+
sqlalchemy_db=get_cached_sqlalchemy_db(),
|
105
|
+
scheduled_operations=get_scheduled_operations()
|
106
|
+
)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
from datetime import timedelta
|
2
|
+
from typing import Any, Callable
|
3
|
+
|
4
|
+
from pydantic import ConfigDict
|
5
|
+
from pydantic.v1 import BaseModel
|
6
|
+
|
7
|
+
from operation_execution.util import every_timedelta_is_time_func
|
8
|
+
from sqlalchemy_db.sqlalchemy_model import OperationDBM
|
9
|
+
|
10
|
+
|
11
|
+
class ScheduledOperation(BaseModel):
|
12
|
+
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
13
|
+
|
14
|
+
type: str
|
15
|
+
input_data: dict[str, Any] | None = None
|
16
|
+
is_time_func: Callable
|
17
|
+
timeout_after_creation: timedelta | None = None
|
18
|
+
|
19
|
+
|
20
|
+
healthcheck_every_0_01_seconds_scheduled_operation = ScheduledOperation(
|
21
|
+
type=OperationDBM.Types.healthcheck_,
|
22
|
+
input_data={"healthcheck": "healthcheck"},
|
23
|
+
is_time_func=every_timedelta_is_time_func(td=timedelta(seconds=0.01))
|
24
|
+
)
|
25
|
+
|
26
|
+
healthcheck_every_3_seconds_scheduled_operation = ScheduledOperation(
|
27
|
+
type=OperationDBM.Types.healthcheck_,
|
28
|
+
input_data={"healthcheck": "healthcheck"},
|
29
|
+
is_time_func=every_timedelta_is_time_func(td=timedelta(seconds=3))
|
30
|
+
)
|
31
|
+
|
32
|
+
healthcheck_every_24_hours_scheduled_operation = ScheduledOperation(
|
33
|
+
type=OperationDBM.Types.healthcheck_,
|
34
|
+
input_data={"healthcheck": "healthcheck"},
|
35
|
+
is_time_func=every_timedelta_is_time_func(td=timedelta(hours=24))
|
36
|
+
)
|
37
|
+
|
38
|
+
raise_fake_error_every_3_seconds_scheduled_operation = ScheduledOperation(
|
39
|
+
type=OperationDBM.Types.raise_fake_error_,
|
40
|
+
input_data={"raise_fake_error": "raise_fake_error"},
|
41
|
+
is_time_func=every_timedelta_is_time_func(td=timedelta(seconds=3))
|
42
|
+
)
|
43
|
+
|
44
|
+
|
45
|
+
def get_scheduled_operations() -> list[ScheduledOperation]:
|
46
|
+
res = []
|
47
|
+
res.append(healthcheck_every_3_seconds_scheduled_operation)
|
48
|
+
res.append(healthcheck_every_24_hours_scheduled_operation)
|
49
|
+
return res
|