Текущая стабильная сборка с исправлением интеграционных косяков

This commit is contained in:
mi
2026-08-20 11:03:32 +03:00
parent c7a80e7256
commit 6e24278b10
12 changed files with 127 additions and 32 deletions
@@ -9,7 +9,7 @@ from urllib.parse import urlsplit
from pydantic import Field, SecretStr, model_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
FIELD_RE = re.compile(r"^UF_CRM_[0-9]+$")
FIELD_RE = re.compile(r"^UF_CRM_[A-Za-z0-9]+$")
MEMBER_RE = re.compile(r"^[A-Za-z0-9_-]{8,128}$")
@@ -107,7 +107,7 @@ class Settings(BaseSettings):
"contact_citizenship_field",
):
if not FIELD_RE.fullmatch(str(getattr(self, name))):
raise ValueError(f"{name} must match UF_CRM_<digits>")
raise ValueError(f"{name} must match UF_CRM_<latin letters or digits>")
if not MEMBER_RE.fullmatch(str(self.portal_member_id)):
raise ValueError("portal_member_id has invalid format")
@@ -5,7 +5,8 @@ import uuid
from dataclasses import dataclass, field
from typing import Any
from sqlalchemy import text
from sqlalchemy import bindparam, text
from sqlalchemy.dialects.postgresql import JSONB
from app.config import Settings
from app.crm import CrmClient, CrmOutcome, CrmResult
@@ -19,6 +20,26 @@ from app.domain import (
)
from app.repository import LeasedTask, LeasedWebhook, Profile, Repository
INSERT_CRM_COMMAND = text(
"""
INSERT INTO bitrix_sync.crm_commands
(id,workflow_id,command_type,safe_request,status,attempt_count,
next_attempt_at,created_at,updated_at)
VALUES (:id,:workflow_id,:type,:safe_request,'in_flight',1,now(),now(),now())
"""
).bindparams(bindparam("safe_request", type_=JSONB()))
UPDATE_CRM_COMMAND = text(
"""
UPDATE bitrix_sync.crm_commands
SET status=:status,safe_error_code=:error,http_status=:http_status,
safe_response=:safe_response,
completed_at=CASE WHEN :terminal THEN now() END,
updated_at=now()
WHERE id=:id
"""
).bindparams(bindparam("safe_response", type_=JSONB()))
class BusinessConflict(Exception):
def __init__(self, code: str, candidates: list[str] | None = None) -> None:
@@ -452,14 +473,7 @@ class WorkflowEngine:
command_id = uuid.uuid4()
async with self.repository.transaction() as connection:
await connection.execute(
text(
"""
INSERT INTO bitrix_sync.crm_commands
(id,workflow_id,command_type,safe_request,status,attempt_count,
next_attempt_at,created_at,updated_at)
VALUES (:id,:workflow_id,:type,:safe_request,'in_flight',1,now(),now(),now())
"""
),
INSERT_CRM_COMMAND,
{
"id": command_id,
"workflow_id": workflow_id,
@@ -479,16 +493,7 @@ class WorkflowEngine:
status = result.outcome.value
async with self.repository.transaction() as connection:
await connection.execute(
text(
"""
UPDATE bitrix_sync.crm_commands
SET status=:status,safe_error_code=:error,http_status=:http_status,
safe_response=:safe_response,
completed_at=CASE WHEN :terminal THEN now() END,
updated_at=now()
WHERE id=:id
"""
),
UPDATE_CRM_COMMAND,
{
"id": command_id,
"status": status,
@@ -506,7 +506,8 @@ class Repository:
queries = {
"queue": "SELECT status, count(*) count FROM han_app.sync_queue GROUP BY status",
"workflows": (
"SELECT state, count(*) count FROM bitrix_sync.workflow_instances GROUP BY state"
"SELECT state AS status, count(*) count "
"FROM bitrix_sync.workflow_instances GROUP BY state"
),
"commands": (
"SELECT status, count(*) count "