Инструменты пользователя

Инструменты сайта


sharixopen:knowledge:scenarios:service_request_pending

Это старая версия документа!


SERVICE_REQUEST в PENDING: партии кандидатов и назначение победителя

Область: ShariX Open. Обработчик: open_service_request_pending, тип SERVICE_REQUEST (2), статус PENDING. Опубликованный Python на 28.10.2026 побайтово совпадает с каноническим результатом генерации Blockly workspace. Выбранную версию и настройки конкретного сервера следует проверять отдельно.

Назначение и границы

Обработчик ищет исполнителя для заказа без назначенного provider. Backend возвращает одну допустимую партию; runtime отправляет предложения параллельно и выбирает первый допустимый положительный ответ. Затем отдельный канонический backend action проверяет возможность назначения и сохраняет provider вместе с переходом PENDING→ACCEPTED. Согласие участника само по себе не переводит заказ в ASSIGNED или PRE_START.

Схемы BPMN описательные, isExecutable=false. Исполняется проверенный Python, сгенерированный из Blockly; Wiki не исполняет XML и не заменяет runtime. Внешний человек, доставка сообщений, API и таймеры показаны отдельно от бизнес-решения.

Порядок решений текущего прохода (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_service_pending_logic" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="pending_Process_pending" name="PENDING: порядок решений одного прохода handler" isExecutable="false">
    <bpmn:documentation>{"notes": ["ShariX Open, опубликованный Python совпадает с renderer Blockly; isExecutable=false.", "Общий deadline поиска проверяется до winner раунда.", "Раунд, курсор и цикл — в памяти; ответ человека не равен назначению в БД."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_pending.py", "repository": "sharix-open-handlers-examples", "sha256": "8521aac05e4d6b39e7afe7e3fd23e01bf889efc28156f0fc24758bd4c47d1649"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_pending.json", "repository": "sharix-open-handlers-examples", "sha256": "350202d5ae40afb1aea68d95e6117cd35b9ed851c9e0142b019dac5de321145f"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_matching.py", "repository": "sharix-open-backend", "sha256": "74d09c8d9a9970eceba0b7b2324a8beb0e9e315dbf72ac8139493fafbbd69a6d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "services/provider_availability.py", "repository": "sharix-open-backend", "sha256": "933d2a029ebbed4cb4e6b9154bb30a5798f445a0c8d9fe0d5fbd6ea3d1f485c5"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/platform_matching.py", "repository": "sharix-open-backend", "sha256": "14814da9f7afa91ab4d39834c5e7b739fdb74359b8df0c4be97fde885e2b92c7"}]}</bpmn:documentation>
    <bpmn:laneSet id="pending_Lanes_pending">
      <bpmn:lane id="pending_Lane_worker" name="После scoped context; defer освобождает worker">
        <bpmn:flowNodeRef>pending_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_deadline</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_move</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_moved</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_end_move</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_outcome</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_accept</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_accepted</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_end_accept</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_retry_winner</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_terminal</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_forget</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_round</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_send</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_recipients</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_defer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_empty</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>pending_retry</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="pending_start" name="Свой статус PENDING, context получен">
      <bpmn:outgoing>pending_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:exclusiveGateway id="pending_deadline" name="Общий срок поиска наступил?">
      <bpmn:incoming>pending_Flow_0</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_1</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_5</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="pending_move" name="move-pending-to-pre-forcemajeur">
      <bpmn:incoming>pending_Flow_1</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="pending_moved" name="Успех / stale?">
      <bpmn:incoming>pending_Flow_2</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_3</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_4</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:endEvent id="pending_end_move" name="Освободить текущую очередь">
      <bpmn:incoming>pending_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:exclusiveGateway id="pending_outcome" name="Текущий / последний исход?">
      <bpmn:incoming>pending_Flow_4</bpmn:incoming>
      <bpmn:incoming>pending_Flow_5</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_6</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_10</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="pending_accept" name="accept-pending-provider: winner id">
      <bpmn:incoming>pending_Flow_6</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_7</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="pending_accepted" name="Успех / stale?">
      <bpmn:incoming>pending_Flow_7</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_8</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_9</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:endEvent id="pending_end_accept" name="Извещение остальных; очередь освобождена">
      <bpmn:incoming>pending_Flow_8</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="pending_retry_winner" name="Defer RECHECK; сохранить того же winner">
      <bpmn:incoming>pending_Flow_9</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="pending_terminal" name="Другой терминальный исход?">
      <bpmn:incoming>pending_Flow_10</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_11</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_12</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="pending_forget" name="Удалить раунд; сохранить cursor/cycle">
      <bpmn:incoming>pending_Flow_11</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_13</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="pending_round" name="Раунд существует?">
      <bpmn:incoming>pending_Flow_12</bpmn:incoming>
      <bpmn:incoming>pending_Flow_13</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_14</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_15</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:sendTask id="pending_send" name="Новая партия: создать и отправить раунд">
      <bpmn:incoming>pending_Flow_14</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_16</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:exclusiveGateway id="pending_recipients" name="Есть адресаты?">
      <bpmn:incoming>pending_Flow_16</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_17</bpmn:outgoing>
      <bpmn:outgoing>pending_Flow_18</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="pending_defer" name="Defer до expires_at; иначе RECHECK">
      <bpmn:incoming>pending_Flow_15</bpmn:incoming>
      <bpmn:incoming>pending_Flow_17</bpmn:incoming>
      <bpmn:outgoing>pending_Flow_19</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="pending_end" name="Следующий проход по ответу / сроку / reconcile">
      <bpmn:incoming>pending_Flow_19</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="pending_empty" name="Нет адресатов: defer RECHECK">
      <bpmn:incoming>pending_Flow_18</bpmn:incoming>
    </bpmn:serviceTask>
    <bpmn:boundaryEvent id="pending_error" name="API исключение" attachedToRef="pending_accept" cancelActivity="true">
      <bpmn:outgoing>pending_Flow_20</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:endEvent id="pending_retry" name="processing_error, общий defer">
      <bpmn:incoming>pending_Flow_20</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="pending_Flow_0" sourceRef="pending_start" targetRef="pending_deadline" name="" />
    <bpmn:sequenceFlow id="pending_Flow_1" sourceRef="pending_deadline" targetRef="pending_move" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_2" sourceRef="pending_move" targetRef="pending_moved" name="" />
    <bpmn:sequenceFlow id="pending_Flow_3" sourceRef="pending_moved" targetRef="pending_end_move" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_4" sourceRef="pending_moved" targetRef="pending_outcome" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_5" sourceRef="pending_deadline" targetRef="pending_outcome" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_6" sourceRef="pending_outcome" targetRef="pending_accept" name="winner" />
    <bpmn:sequenceFlow id="pending_Flow_7" sourceRef="pending_accept" targetRef="pending_accepted" name="" />
    <bpmn:sequenceFlow id="pending_Flow_8" sourceRef="pending_accepted" targetRef="pending_end_accept" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_9" sourceRef="pending_accepted" targetRef="pending_retry_winner" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_10" sourceRef="pending_outcome" targetRef="pending_terminal" name="Иное / нет" />
    <bpmn:sequenceFlow id="pending_Flow_11" sourceRef="pending_terminal" targetRef="pending_forget" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_12" sourceRef="pending_terminal" targetRef="pending_round" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_13" sourceRef="pending_forget" targetRef="pending_round" name="" />
    <bpmn:sequenceFlow id="pending_Flow_14" sourceRef="pending_round" targetRef="pending_send" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_15" sourceRef="pending_round" targetRef="pending_defer" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_16" sourceRef="pending_send" targetRef="pending_recipients" name="" />
    <bpmn:sequenceFlow id="pending_Flow_17" sourceRef="pending_recipients" targetRef="pending_defer" name="Да" />
    <bpmn:sequenceFlow id="pending_Flow_18" sourceRef="pending_recipients" targetRef="pending_empty" name="Нет" />
    <bpmn:sequenceFlow id="pending_Flow_19" sourceRef="pending_defer" targetRef="pending_end" name="" />
    <bpmn:sequenceFlow id="pending_Flow_20" sourceRef="pending_error" targetRef="pending_retry" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_service_pending_logic">
    <bpmn:participant id="pending_Pool_pending" name="PENDING: порядок решений одного прохода handler" processRef="pending_Process_pending" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_service_pending_logic">
    <bpmndi:BPMNPlane id="Plane_service_pending_logic" bpmnElement="Collaboration_service_pending_logic">
      <bpmndi:BPMNShape id="pending_DI_Pool_pending" bpmnElement="pending_Pool_pending" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1790" height="1360" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_Lane_worker" bpmnElement="pending_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1760" height="1360" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_start" bpmnElement="pending_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_deadline" bpmnElement="pending_deadline">
        <dc:Bounds x="405.0" y="75.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_move" bpmnElement="pending_move">
        <dc:Bounds x="655.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_moved" bpmnElement="pending_moved">
        <dc:Bounds x="1005.0" y="75.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_end_move" bpmnElement="pending_end_move">
        <dc:Bounds x="1312.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_outcome" bpmnElement="pending_outcome">
        <dc:Bounds x="405.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_accept" bpmnElement="pending_accept">
        <dc:Bounds x="655.0" y="305.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_accepted" bpmnElement="pending_accepted">
        <dc:Bounds x="1005.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_end_accept" bpmnElement="pending_end_accept">
        <dc:Bounds x="1312.0" y="322.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_retry_winner" bpmnElement="pending_retry_winner">
        <dc:Bounds x="955.0" y="545.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_terminal" bpmnElement="pending_terminal">
        <dc:Bounds x="405.0" y="555.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_forget" bpmnElement="pending_forget">
        <dc:Bounds x="655.0" y="765.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_round" bpmnElement="pending_round">
        <dc:Bounds x="405.0" y="1005.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_send" bpmnElement="pending_send">
        <dc:Bounds x="655.0" y="995.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_recipients" bpmnElement="pending_recipients">
        <dc:Bounds x="1005.0" y="1005.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_defer" bpmnElement="pending_defer">
        <dc:Bounds x="1255.0" y="995.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_end" bpmnElement="pending_end">
        <dc:Bounds x="1612.0" y="1012.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_empty" bpmnElement="pending_empty">
        <dc:Bounds x="955.0" y="1225.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_error" bpmnElement="pending_error">
        <dc:Bounds x="762.0" y="357.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="pending_DI_retry" bpmnElement="pending_retry">
        <dc:Bounds x="1612.0" y="562.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="pending_DI_Flow_0" bpmnElement="pending_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="405.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_1" bpmnElement="pending_Flow_1">
        <di:waypoint x="455.0" y="100.0" />
        <di:waypoint x="655.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_2" bpmnElement="pending_Flow_2">
        <di:waypoint x="805.0" y="100.0" />
        <di:waypoint x="1005.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_3" bpmnElement="pending_Flow_3">
        <di:waypoint x="1055.0" y="100.0" />
        <di:waypoint x="1312.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_4" bpmnElement="pending_Flow_4">
        <di:waypoint x="1055.0" y="100.0" />
        <di:waypoint x="1150.0" y="100.0" />
        <di:waypoint x="1450.0" y="100.0" />
        <di:waypoint x="1450.0" y="260.0" />
        <di:waypoint x="430.0" y="260.0" />
        <di:waypoint x="430.0" y="315.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_5" bpmnElement="pending_Flow_5">
        <di:waypoint x="430.0" y="125.0" />
        <di:waypoint x="430.0" y="315.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_6" bpmnElement="pending_Flow_6">
        <di:waypoint x="455.0" y="340.0" />
        <di:waypoint x="655.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_7" bpmnElement="pending_Flow_7">
        <di:waypoint x="805.0" y="340.0" />
        <di:waypoint x="1005.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_8" bpmnElement="pending_Flow_8">
        <di:waypoint x="1055.0" y="340.0" />
        <di:waypoint x="1312.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_9" bpmnElement="pending_Flow_9">
        <di:waypoint x="1030.0" y="365.0" />
        <di:waypoint x="1030.0" y="545.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_10" bpmnElement="pending_Flow_10">
        <di:waypoint x="430.0" y="365.0" />
        <di:waypoint x="430.0" y="555.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_11" bpmnElement="pending_Flow_11">
        <di:waypoint x="455.0" y="580.0" />
        <di:waypoint x="555.0" y="580.0" />
        <di:waypoint x="555.0" y="800.0" />
        <di:waypoint x="655.0" y="800.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_12" bpmnElement="pending_Flow_12">
        <di:waypoint x="455.0" y="580.0" />
        <di:waypoint x="550.0" y="580.0" />
        <di:waypoint x="580.0" y="580.0" />
        <di:waypoint x="580.0" y="960.0" />
        <di:waypoint x="430.0" y="960.0" />
        <di:waypoint x="430.0" y="1005.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_13" bpmnElement="pending_Flow_13">
        <di:waypoint x="805.0" y="800.0" />
        <di:waypoint x="850.0" y="800.0" />
        <di:waypoint x="850.0" y="930.0" />
        <di:waypoint x="430.0" y="930.0" />
        <di:waypoint x="430.0" y="1005.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_14" bpmnElement="pending_Flow_14">
        <di:waypoint x="455.0" y="1030.0" />
        <di:waypoint x="655.0" y="1030.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_15" bpmnElement="pending_Flow_15">
        <di:waypoint x="455.0" y="1030.0" />
        <di:waypoint x="550.0" y="1030.0" />
        <di:waypoint x="580.0" y="1030.0" />
        <di:waypoint x="580.0" y="950.0" />
        <di:waypoint x="1330.0" y="950.0" />
        <di:waypoint x="1330.0" y="995.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_16" bpmnElement="pending_Flow_16">
        <di:waypoint x="805.0" y="1030.0" />
        <di:waypoint x="1005.0" y="1030.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_17" bpmnElement="pending_Flow_17">
        <di:waypoint x="1055.0" y="1030.0" />
        <di:waypoint x="1255.0" y="1030.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_18" bpmnElement="pending_Flow_18">
        <di:waypoint x="1030.0" y="1055.0" />
        <di:waypoint x="1030.0" y="1225.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_19" bpmnElement="pending_Flow_19">
        <di:waypoint x="1405.0" y="1030.0" />
        <di:waypoint x="1612.0" y="1030.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="pending_DI_Flow_20" bpmnElement="pending_Flow_20">
        <di:waypoint x="798.0" y="375.0" />
        <di:waypoint x="840.0" y="375.0" />
        <di:waypoint x="1500.0" y="375.0" />
        <di:waypoint x="1500.0" y="510.0" />
        <di:waypoint x="1630.0" y="510.0" />
        <di:waypoint x="1630.0" y="562.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

После проверки своего статуса и scoped order context записывается локальная причина provider_matching_batch. Чужой статус запрашивает очистку Ticket и комнаты. 404 scoped context очищает устаревшее локальное состояние; отсутствие/неоднозначность связанного Orders — ошибка API, а не пустой список кандидатов.

Сначала проверяется общий предел поиска: для ASAP — asap_deadline, для планового заказа — pre_start_at. Если срок наступил, handler пробует move-pending-to-pre-forcemajeur. При успехе/stale текущая очередь освобождается. При обработанном отрицательном результате выполнение проходит дальше; исключение API прерывает проход и попадает в общий defer.

Лишь затем рассматривается раунд:

  • winner → accept-pending-provider. При неуспехе сохраняется тот же победитель, defer по SERVICE_REQUEST_PENDING_RECHECK_SECONDS; новая партия пока не выбирается.
  • Иной терминальный исход, например timed_out или no_winner, удаляет раунд и кэш партии, но сохраняет cursor/cycle поиска.
  • Если раунда нет, создаётся следующая партия и выполняется одна попытка отправки. Нет адресатов — обычный RECHECK, без автоматического объявления полного форс-мажора.
  • При существующем раунде defer назначается до его expires_at; без даты — по RECHECK. Ответ/событие может сделать Ticket готовым раньше.

В отличие от ASSIGNED здесь нет отдельной повторной проверки winner сразу после send. Ответы, включая разобранные после отправки queued intents, учитываются последующим проходом. Общий предел поиска всё равно проверяется первым: даже полученное в пределах TTL согласие не обещает назначения после наступления общего deadline.

Откуда берутся кандидаты (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_service_pending_candidates" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="batch_Process_batch" name="Получение партии: локальные ограничения, внешний ranking, cursor" isExecutable="false">
    <bpmn:documentation>{"notes": ["ShariX Open, опубликованный Python совпадает с renderer Blockly; isExecutable=false.", "Общий deadline поиска проверяется до winner раунда.", "Раунд, курсор и цикл — в памяти; ответ человека не равен назначению в БД.", "Размер партии задаёт backend. Пустой хвост cursor запускает свежий цикл.", "Platform — необязательный внешний порт ранжирования; окончательные кандидаты остаются локально допустимыми."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_pending.py", "repository": "sharix-open-handlers-examples", "sha256": "8521aac05e4d6b39e7afe7e3fd23e01bf889efc28156f0fc24758bd4c47d1649"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_pending.json", "repository": "sharix-open-handlers-examples", "sha256": "350202d5ae40afb1aea68d95e6117cd35b9ed851c9e0142b019dac5de321145f"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_matching.py", "repository": "sharix-open-backend", "sha256": "74d09c8d9a9970eceba0b7b2324a8beb0e9e315dbf72ac8139493fafbbd69a6d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "services/provider_availability.py", "repository": "sharix-open-backend", "sha256": "933d2a029ebbed4cb4e6b9154bb30a5798f445a0c8d9fe0d5fbd6ea3d1f485c5"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/platform_matching.py", "repository": "sharix-open-backend", "sha256": "14814da9f7afa91ab4d39834c5e7b739fdb74359b8df0c4be97fde885e2b92c7"}]}</bpmn:documentation>
    <bpmn:laneSet id="batch_Lanes_batch">
      <bpmn:lane id="batch_Lane_worker" name="Runtime + scoped backend API order.candidates">
        <bpmn:flowNodeRef>batch_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_cursor</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_local</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_rank</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_refresh</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_sort</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_page</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_empty</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_cycle</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_offers</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>batch_save</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="batch_start" name="Нужен новый раунд">
      <bpmn:outgoing>batch_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:serviceTask id="batch_cursor" name="Продолжить cursor; исчерпанный список → новый cycle">
      <bpmn:incoming>batch_Flow_0</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="batch_local" name="Service/company/role/resource, доступность, конфликты; один JID">
      <bpmn:incoming>batch_Flow_1</bpmn:incoming>
      <bpmn:incoming>batch_Flow_10</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_2</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="batch_rank" name="Вызвать настроенный matching port Platform">
      <bpmn:incoming>batch_Flow_2</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_3</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="batch_refresh" name="Если был HTTP: заново собрать локально допустимых">
      <bpmn:incoming>batch_Flow_3</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="batch_sort" name="Применить допустимый ranking / local fallback">
      <bpmn:incoming>batch_Flow_4</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="batch_page" name="Хвост после cursor; ASAP не смешивает dispatch groups">
      <bpmn:incoming>batch_Flow_5</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_6</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="batch_empty" name="Партия пуста?">
      <bpmn:incoming>batch_Flow_6</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_7</bpmn:outgoing>
      <bpmn:outgoing>batch_Flow_9</bpmn:outgoing>
      <bpmn:outgoing>batch_Flow_11</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="batch_cycle" name="Ненулевой cursor: сбросить и запросить один раз заново">
      <bpmn:incoming>batch_Flow_9</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_10</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="batch_wait" name="Пустой начальный список: RECHECK">
      <bpmn:incoming>batch_Flow_11</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:serviceTask id="batch_offers" name="Backend batch size; runtime UUID offers и now + TTL">
      <bpmn:incoming>batch_Flow_7</bpmn:incoming>
      <bpmn:outgoing>batch_Flow_8</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="batch_save" name="Сохранить cursor/has_more и создать parallel round">
      <bpmn:incoming>batch_Flow_8</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="batch_Flow_0" sourceRef="batch_start" targetRef="batch_cursor" name="" />
    <bpmn:sequenceFlow id="batch_Flow_1" sourceRef="batch_cursor" targetRef="batch_local" name="" />
    <bpmn:sequenceFlow id="batch_Flow_2" sourceRef="batch_local" targetRef="batch_rank" name="" />
    <bpmn:sequenceFlow id="batch_Flow_3" sourceRef="batch_rank" targetRef="batch_refresh" name="" />
    <bpmn:sequenceFlow id="batch_Flow_4" sourceRef="batch_refresh" targetRef="batch_sort" name="" />
    <bpmn:sequenceFlow id="batch_Flow_5" sourceRef="batch_sort" targetRef="batch_page" name="" />
    <bpmn:sequenceFlow id="batch_Flow_6" sourceRef="batch_page" targetRef="batch_empty" name="" />
    <bpmn:sequenceFlow id="batch_Flow_7" sourceRef="batch_empty" targetRef="batch_offers" name="Нет" />
    <bpmn:sequenceFlow id="batch_Flow_8" sourceRef="batch_offers" targetRef="batch_save" name="" />
    <bpmn:sequenceFlow id="batch_Flow_9" sourceRef="batch_empty" targetRef="batch_cycle" name="Да, cursor &gt; 0" />
    <bpmn:sequenceFlow id="batch_Flow_10" sourceRef="batch_cycle" targetRef="batch_local" name="" />
    <bpmn:sequenceFlow id="batch_Flow_11" sourceRef="batch_empty" targetRef="batch_wait" name="Да, cursor = 0" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_service_pending_candidates">
    <bpmn:participant id="batch_Pool_batch" name="Получение партии: локальные ограничения, внешний ranking, cursor" processRef="batch_Process_batch" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_service_pending_candidates">
    <bpmndi:BPMNPlane id="Plane_service_pending_candidates" bpmnElement="Collaboration_service_pending_candidates">
      <bpmndi:BPMNShape id="batch_DI_Pool_batch" bpmnElement="batch_Pool_batch" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1840" height="890" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_Lane_worker" bpmnElement="batch_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1810" height="890" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_start" bpmnElement="batch_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_cursor" bpmnElement="batch_cursor">
        <dc:Bounds x="365.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_local" bpmnElement="batch_local">
        <dc:Bounds x="675.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_rank" bpmnElement="batch_rank">
        <dc:Bounds x="985.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_refresh" bpmnElement="batch_refresh">
        <dc:Bounds x="1295.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_sort" bpmnElement="batch_sort">
        <dc:Bounds x="1605.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_page" bpmnElement="batch_page">
        <dc:Bounds x="1605.0" y="305.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_empty" bpmnElement="batch_empty">
        <dc:Bounds x="1345.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_cycle" bpmnElement="batch_cycle">
        <dc:Bounds x="985.0" y="535.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_wait" bpmnElement="batch_wait">
        <dc:Bounds x="1352.0" y="772.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_offers" bpmnElement="batch_offers">
        <dc:Bounds x="985.0" y="305.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="batch_DI_save" bpmnElement="batch_save">
        <dc:Bounds x="732.0" y="322.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="batch_DI_Flow_0" bpmnElement="batch_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="365.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_1" bpmnElement="batch_Flow_1">
        <di:waypoint x="515.0" y="100.0" />
        <di:waypoint x="675.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_2" bpmnElement="batch_Flow_2">
        <di:waypoint x="825.0" y="100.0" />
        <di:waypoint x="985.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_3" bpmnElement="batch_Flow_3">
        <di:waypoint x="1135.0" y="100.0" />
        <di:waypoint x="1295.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_4" bpmnElement="batch_Flow_4">
        <di:waypoint x="1445.0" y="100.0" />
        <di:waypoint x="1605.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_5" bpmnElement="batch_Flow_5">
        <di:waypoint x="1680.0" y="135.0" />
        <di:waypoint x="1680.0" y="305.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_6" bpmnElement="batch_Flow_6">
        <di:waypoint x="1605.0" y="340.0" />
        <di:waypoint x="1395.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_7" bpmnElement="batch_Flow_7">
        <di:waypoint x="1345.0" y="340.0" />
        <di:waypoint x="1135.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_8" bpmnElement="batch_Flow_8">
        <di:waypoint x="985.0" y="340.0" />
        <di:waypoint x="768.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_9" bpmnElement="batch_Flow_9">
        <di:waypoint x="1345.0" y="340.0" />
        <di:waypoint x="1240.0" y="340.0" />
        <di:waypoint x="1240.0" y="570.0" />
        <di:waypoint x="1135.0" y="570.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_10" bpmnElement="batch_Flow_10">
        <di:waypoint x="1135.0" y="570.0" />
        <di:waypoint x="1180.0" y="570.0" />
        <di:waypoint x="1250.0" y="570.0" />
        <di:waypoint x="1250.0" y="30.0" />
        <di:waypoint x="750.0" y="30.0" />
        <di:waypoint x="750.0" y="65.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="batch_DI_Flow_11" bpmnElement="batch_Flow_11">
        <di:waypoint x="1370.0" y="365.0" />
        <di:waypoint x="1370.0" y="772.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Scoped order.candidates доступен handler текущего PENDING. Размер партии задаёт backend через SERVICE_REQUEST_PENDING_BATCH_SIZE. Параметры cycle/batch/request/TTL в ответе не означают, что backend сохраняет раунды или резервирует кандидатов.

Локальный подбор последовательно учитывает услугу и компанию, активность Provider и пользователя, роль METASERVICE-PROVIDER, ресурсные и иные hard eligibility-условия, конфликтующие активные заказы, доступность и корректный JID. До ограничения размера партии остаётся один приоритетный Provider на bare JID, чтобы несколько старых записей одного пользователя не заняли всю партию.

Для ASAP сначала идут непосредственные online-предложения, затем gap-предложения по меньшему оставшемуся ожиданию. В одной ASAP-партии не смешиваются разные dispatch groups. Для планового заказа gap допустим, если исполнитель сможет быть готов не позднее time_start.

Необязательное ранжирование Platform

Публичный integration port может получить порядок кандидатов от Platform. Это подсказка порядка, не разрешение исполнителю и не lease доступности. После попытки внешнего HTTP локальный набор строится заново. Неизвестные, чужие по метасервису или уже недопустимые provider id не становятся допустимыми из-за удалённого ответа. Для ASAP сохраняется порядок локальных dispatch groups; при недоступном/неподходящем ranking действует локальный порядок. Внутренний алгоритм Platform этой страницей не описывается.

Партии и циклы

Runtime хранит after_provider_id, номер партии, цикл и has_more. После исчерпания списка начинается новый цикл с нулевым cursor. Если cursor исчез из текущего допустимого порядка, backend возвращает пустой хвост; runtime сбрасывает его и может сделать один дополнительный запрос с начала. Пустой начальный список ведёт к ожиданию RECHECK.

Для непустой партии runtime создаёт новые offer UUID и общий expires_at = now + OFFER_TTL. Cursor и цикл находятся в памяти процесса; отказ от завершённого раунда их не сбрасывает, а рестарт/full cleanup — сбрасывает. Это не постоянный журнал уже уведомлённых исполнителей и не гарантия отсутствия повторных предложений после рестарта.

Человек, окно ответа и окончательное назначение (BPMN)

Схема BPMN

Загрузка схемы…

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_service_pending_round" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="round_Process_round" name="Handler и backend: предложение → ответ → окончательное назначение" isExecutable="false">
    <bpmn:documentation>{"notes": ["ShariX Open, опубликованный Python совпадает с renderer Blockly; isExecutable=false.", "Общий deadline поиска проверяется до winner раунда.", "Раунд, курсор и цикл — в памяти; ответ человека не равен назначению в БД.", "first_accept / parallel / одна попытка; TTL не равен общему сроку поиска.", "Backend подтверждает текущий scope, отсутствие provider, hard eligibility, concurrency и requirements."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_pending.py", "repository": "sharix-open-handlers-examples", "sha256": "8521aac05e4d6b39e7afe7e3fd23e01bf889efc28156f0fc24758bd4c47d1649"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_pending.json", "repository": "sharix-open-handlers-examples", "sha256": "350202d5ae40afb1aea68d95e6117cd35b9ed851c9e0142b019dac5de321145f"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_matching.py", "repository": "sharix-open-backend", "sha256": "74d09c8d9a9970eceba0b7b2324a8beb0e9e315dbf72ac8139493fafbbd69a6d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "services/provider_availability.py", "repository": "sharix-open-backend", "sha256": "933d2a029ebbed4cb4e6b9154bb30a5798f445a0c8d9fe0d5fbd6ea3d1f485c5"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/platform_matching.py", "repository": "sharix-open-backend", "sha256": "14814da9f7afa91ab4d39834c5e7b739fdb74359b8df0c4be97fde885e2b92c7"}]}</bpmn:documentation>
    <bpmn:laneSet id="round_Lanes_round">
      <bpmn:lane id="round_Lane_worker" name="Раунд в памяти; каноническое изменение Orders/Ticket">
        <bpmn:flowNodeRef>round_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_send</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_response</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_validate</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_decision</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_winner</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_deadline</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_backend</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_ok</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_assigned</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_retry</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_force</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_timer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>round_next</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="round_start" name="Получена партия кандидатов">
      <bpmn:outgoing>round_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:sendTask id="round_send" name="Parallel order.action.required accept/decline">
      <bpmn:incoming>round_Flow_0</bpmn:incoming>
      <bpmn:outgoing>round_Flow_1</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:eventBasedGateway id="round_wait" name="Ответы или TTL">
      <bpmn:incoming>round_Flow_1</bpmn:incoming>
      <bpmn:incoming>round_Flow_7</bpmn:incoming>
      <bpmn:outgoing>round_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>round_Flow_14</bpmn:outgoing>
    </bpmn:eventBasedGateway>
    <bpmn:intermediateCatchEvent id="round_response" name="Прямой XMPP или trusted web relay">
      <bpmn:incoming>round_Flow_2</bpmn:incoming>
      <bpmn:outgoing>round_Flow_3</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:intermediateCatchEvent>
    <bpmn:serviceTask id="round_validate" name="Проверить JID, round/order/status/offer, срок, повтор">
      <bpmn:incoming>round_Flow_3</bpmn:incoming>
      <bpmn:outgoing>round_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="round_decision" name="Решение first_accept?">
      <bpmn:incoming>round_Flow_4</bpmn:incoming>
      <bpmn:outgoing>round_Flow_5</bpmn:outgoing>
      <bpmn:outgoing>round_Flow_6</bpmn:outgoing>
      <bpmn:outgoing>round_Flow_7</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="round_winner" name="Сохранить winner; сделать Ticket ready">
      <bpmn:incoming>round_Flow_5</bpmn:incoming>
      <bpmn:outgoing>round_Flow_8</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="round_deadline" name="Следующий проход: общий срок ещё позволяет?">
      <bpmn:incoming>round_Flow_8</bpmn:incoming>
      <bpmn:outgoing>round_Flow_9</bpmn:outgoing>
      <bpmn:outgoing>round_Flow_10</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="round_backend" name="accept-pending-provider под lock и gates">
      <bpmn:incoming>round_Flow_9</bpmn:incoming>
      <bpmn:outgoing>round_Flow_11</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="round_ok" name="Доменный успех?">
      <bpmn:incoming>round_Flow_11</bpmn:incoming>
      <bpmn:outgoing>round_Flow_12</bpmn:outgoing>
      <bpmn:outgoing>round_Flow_13</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:endEvent id="round_assigned" name="Provider сохранён; PENDING → ACCEPTED">
      <bpmn:incoming>round_Flow_12</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="round_retry" name="Отказ: тот же winner на RECHECK">
      <bpmn:incoming>round_Flow_13</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="round_force" name="Истёк общий срок: попытка PRE_FORCEMAJEUER">
      <bpmn:incoming>round_Flow_10</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:intermediateCatchEvent id="round_timer" name="round.expires_at">
      <bpmn:incoming>round_Flow_14</bpmn:incoming>
      <bpmn:outgoing>round_Flow_15</bpmn:outgoing>
      <bpmn:timerEventDefinition>
        <bpmn:timeDate xsi:type="bpmn:tFormalExpression">round_expires_at</bpmn:timeDate>
      </bpmn:timerEventDefinition>
    </bpmn:intermediateCatchEvent>
    <bpmn:endEvent id="round_next" name="Нет winner: новая партия в следующем проходе">
      <bpmn:incoming>round_Flow_6</bpmn:incoming>
      <bpmn:incoming>round_Flow_15</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="round_Flow_0" sourceRef="round_start" targetRef="round_send" name="" />
    <bpmn:sequenceFlow id="round_Flow_1" sourceRef="round_send" targetRef="round_wait" name="" />
    <bpmn:sequenceFlow id="round_Flow_2" sourceRef="round_wait" targetRef="round_response" name="" />
    <bpmn:sequenceFlow id="round_Flow_3" sourceRef="round_response" targetRef="round_validate" name="" />
    <bpmn:sequenceFlow id="round_Flow_4" sourceRef="round_validate" targetRef="round_decision" name="" />
    <bpmn:sequenceFlow id="round_Flow_5" sourceRef="round_decision" targetRef="round_winner" name="accept" />
    <bpmn:sequenceFlow id="round_Flow_6" sourceRef="round_decision" targetRef="round_next" name="Все decline / нет winner" />
    <bpmn:sequenceFlow id="round_Flow_7" sourceRef="round_decision" targetRef="round_wait" name="Отклонён / ещё ждём" />
    <bpmn:sequenceFlow id="round_Flow_8" sourceRef="round_winner" targetRef="round_deadline" name="" />
    <bpmn:sequenceFlow id="round_Flow_9" sourceRef="round_deadline" targetRef="round_backend" name="Да" />
    <bpmn:sequenceFlow id="round_Flow_10" sourceRef="round_deadline" targetRef="round_force" name="Нет" />
    <bpmn:sequenceFlow id="round_Flow_11" sourceRef="round_backend" targetRef="round_ok" name="" />
    <bpmn:sequenceFlow id="round_Flow_12" sourceRef="round_ok" targetRef="round_assigned" name="Да" />
    <bpmn:sequenceFlow id="round_Flow_13" sourceRef="round_ok" targetRef="round_retry" name="Нет" />
    <bpmn:sequenceFlow id="round_Flow_14" sourceRef="round_wait" targetRef="round_timer" name="" />
    <bpmn:sequenceFlow id="round_Flow_15" sourceRef="round_timer" targetRef="round_next" name="timed_out" />
  </bpmn:process>
  <bpmn:process id="providers_Process_providers" name="Кандидаты партии: независимые ответы; отправка не доказывает прочтение" isExecutable="false">
    <bpmn:documentation>{"notes": ["ShariX Open, опубликованный Python совпадает с renderer Blockly; isExecutable=false.", "Общий deadline поиска проверяется до winner раунда.", "Раунд, курсор и цикл — в памяти; ответ человека не равен назначению в БД.", "first_accept / parallel / одна попытка; TTL не равен общему сроку поиска.", "Backend подтверждает текущий scope, отсутствие provider, hard eligibility, concurrency и requirements."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_service_request_pending.py", "repository": "sharix-open-handlers-examples", "sha256": "8521aac05e4d6b39e7afe7e3fd23e01bf889efc28156f0fc24758bd4c47d1649"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_service_request_pending.json", "repository": "sharix-open-handlers-examples", "sha256": "350202d5ae40afb1aea68d95e6117cd35b9ed851c9e0142b019dac5de321145f"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "catalog.py", "repository": "sharix-open-handlers-examples", "sha256": "e3dcb72b7e620e2837adacd7af053f35b04cdff475789496d9c114e17d57dfde"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/blockly_runtime.py", "repository": "sharix-open-handlers-backend", "sha256": "3e222150cbff315077c6c9b160d46e59856cedf6d6591d213e958c63cb2f2428"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/requesters.py", "repository": "sharix-open-handlers-backend", "sha256": "965a348cea477722bbaf4c8c6b06023eb238b71664a332f7ea8c90bfe72ea808"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_action_messages.py", "repository": "sharix-open-handlers-backend", "sha256": "046c262c0aabb02104fefca4e887324f99df22731e7726063f614aaf8839ca5c"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_blockly_codegen.py", "repository": "sharix-open-handlers-backend", "sha256": "bce71eab622922f8dd0954222842349799b60e18a0ab6310cc3e5f305603661e"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "ticket_codegen_contract.json", "repository": "sharix-open-handlers-backend", "sha256": "0bfd2b0ebb07bd380ed3c867386536ab88ef7dfa6e13f1cd8c91d32bb02c1ae9"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "lib/tickets.py", "repository": "sharix-open-tickets", "sha256": "0d260c17947f9a186d07af2749159780e3c7354a95b4bafe9d67493663c96883"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/handler_auth.py", "repository": "sharix-open-tickets", "sha256": "ac76dc45aaa9742e5e1da0b98aae914bb2e287048d33e97b4a245a6997bc8425"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/handler_order_workflow.py", "repository": "sharix-open-backend", "sha256": "35624ded6e67110437a25dd07caef214a04251eb0136194ae939fa32fef17e84"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "apiviews/open_api.py", "repository": "sharix-open-backend", "sha256": "cb8fdda304d29c2cc5c0fc938759a13c60022871b7b93d77883d521820021ad3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_handler_relay.py", "repository": "sharix-open-backend", "sha256": "e49a7876169403970d995af464357e2134af19a398372c55db2a5b40681d731e"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/handler_order_context.py", "repository": "sharix-open-backend", "sha256": "f3c0731e74d30dbe5e59bd53040a06ee108f14f7aad04771e65d741cffeb7179"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_workflow_policy.py", "repository": "sharix-open-backend", "sha256": "3266c6ecab490a0e19c8bbc02041387b86fe4b14068750e545ba9bde8bf51326"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_actions.py", "repository": "sharix-open-backend", "sha256": "27ce243408a46f1b700d94bf78a25c68ef21d51078bb03627174e4a424d82ef0"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_permissions.py", "repository": "sharix-open-backend", "sha256": "9c1636daa80c4da68c3ae5cf347e279127d142eeff91e969559e8bd54ca3d81d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "urls.py", "repository": "sharix-open-backend", "sha256": "61ffd2f0563291da2dcc9488a5443cb5e2c0395108740a6700034cfd90548158"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_lifecycle.py", "repository": "sharix-open-backend", "sha256": "66dd2c4db9da3aaf90cb080946c1920a4f9953d62d1e6c9e224dd52564c4d661"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_provider_requirements.py", "repository": "sharix-open-backend", "sha256": "392f1f9180a098a4749b5fe5b7948e34530ccdb2befed646e538cdb7a5ddcada"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "core/order_rounds.py", "repository": "sharix-open-handlers-backend", "sha256": "e27a9190374c3888930f60e26686c11f69069bbbefd4511d21ad7267301321eb"}, {"commit": "50baf376e224d915a87d63240f3f339b3dda9afa", "path": "settings_schema.py", "repository": "sharix-open-handlers-backend", "sha256": "8ea8494405c6808834f4be7b171ffb8a969e1dd9b1654d36a8c21fbc9e3599c3"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/order_matching.py", "repository": "sharix-open-backend", "sha256": "74d09c8d9a9970eceba0b7b2324a8beb0e9e315dbf72ac8139493fafbbd69a6d"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "services/provider_availability.py", "repository": "sharix-open-backend", "sha256": "933d2a029ebbed4cb4e6b9154bb30a5798f445a0c8d9fe0d5fbd6ea3d1f485c5"}, {"commit": "778a3280cee115ba0efe3fdff7b0e708b0c10093", "path": "lib/platform_matching.py", "repository": "sharix-open-backend", "sha256": "14814da9f7afa91ab4d39834c5e7b739fdb74359b8df0c4be97fde885e2b92c7"}]}</bpmn:documentation>
    <bpmn:laneSet id="providers_Lanes_providers">
      <bpmn:lane id="providers_Lane_worker" name="Внешние участники">
        <bpmn:flowNodeRef>providers_notice</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>providers_choose</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>providers_reply</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>providers_end</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="providers_notice" name="Получить предложение с offer/round id">
      <bpmn:outgoing>providers_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:userTask id="providers_choose" name="Согласиться, отказаться либо не ответить">
      <bpmn:incoming>providers_Flow_0</bpmn:incoming>
      <bpmn:outgoing>providers_Flow_1</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sendTask id="providers_reply" name="Отправить ответ до TTL">
      <bpmn:incoming>providers_Flow_1</bpmn:incoming>
      <bpmn:outgoing>providers_Flow_2</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="providers_end" name="Ответ ≠ назначение в БД">
      <bpmn:incoming>providers_Flow_2</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="providers_Flow_0" sourceRef="providers_notice" targetRef="providers_choose" name="" />
    <bpmn:sequenceFlow id="providers_Flow_1" sourceRef="providers_choose" targetRef="providers_reply" name="" />
    <bpmn:sequenceFlow id="providers_Flow_2" sourceRef="providers_reply" targetRef="providers_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_service_pending_round">
    <bpmn:participant id="round_Pool_round" name="Handler и backend: предложение → ответ → окончательное назначение" processRef="round_Process_round" />
    <bpmn:participant id="providers_Pool_providers" name="Кандидаты партии: независимые ответы; отправка не доказывает прочтение" processRef="providers_Process_providers" />
    <bpmn:messageFlow id="Message_service_pending_round_0" sourceRef="round_send" targetRef="providers_notice" name="Параллельная отправка, popup_policy=fullscreen_offer" />
    <bpmn:messageFlow id="Message_service_pending_round_1" sourceRef="providers_reply" targetRef="round_response" name="Actor сохранён; круг/срок/участник проверяются" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_service_pending_round">
    <bpmndi:BPMNPlane id="Plane_service_pending_round" bpmnElement="Collaboration_service_pending_round">
      <bpmndi:BPMNShape id="round_DI_Pool_round" bpmnElement="round_Pool_round" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="2150" height="890" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_Lane_worker" bpmnElement="round_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="2120" height="890" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_start" bpmnElement="round_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_send" bpmnElement="round_send">
        <dc:Bounds x="365.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_wait" bpmnElement="round_wait">
        <dc:Bounds x="725.0" y="75.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_response" bpmnElement="round_response">
        <dc:Bounds x="1042.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_validate" bpmnElement="round_validate">
        <dc:Bounds x="1295.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_decision" bpmnElement="round_decision">
        <dc:Bounds x="1655.0" y="75.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_winner" bpmnElement="round_winner">
        <dc:Bounds x="1915.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_deadline" bpmnElement="round_deadline">
        <dc:Bounds x="1965.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_backend" bpmnElement="round_backend">
        <dc:Bounds x="1605.0" y="305.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_ok" bpmnElement="round_ok">
        <dc:Bounds x="1345.0" y="315.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_assigned" bpmnElement="round_assigned">
        <dc:Bounds x="1042.0" y="322.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_retry" bpmnElement="round_retry">
        <dc:Bounds x="1352.0" y="552.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_force" bpmnElement="round_force">
        <dc:Bounds x="1972.0" y="552.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_timer" bpmnElement="round_timer">
        <dc:Bounds x="1042.0" y="772.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="round_DI_next" bpmnElement="round_next">
        <dc:Bounds x="1662.0" y="772.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="round_DI_Flow_0" bpmnElement="round_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="365.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_1" bpmnElement="round_Flow_1">
        <di:waypoint x="515.0" y="100.0" />
        <di:waypoint x="725.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_2" bpmnElement="round_Flow_2">
        <di:waypoint x="775.0" y="100.0" />
        <di:waypoint x="1042.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_3" bpmnElement="round_Flow_3">
        <di:waypoint x="1078.0" y="100.0" />
        <di:waypoint x="1295.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_4" bpmnElement="round_Flow_4">
        <di:waypoint x="1445.0" y="100.0" />
        <di:waypoint x="1655.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_5" bpmnElement="round_Flow_5">
        <di:waypoint x="1705.0" y="100.0" />
        <di:waypoint x="1915.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_6" bpmnElement="round_Flow_6">
        <di:waypoint x="1705.0" y="100.0" />
        <di:waypoint x="1800.0" y="100.0" />
        <di:waypoint x="1830.0" y="100.0" />
        <di:waypoint x="1830.0" y="720.0" />
        <di:waypoint x="1680.0" y="720.0" />
        <di:waypoint x="1680.0" y="772.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_7" bpmnElement="round_Flow_7">
        <di:waypoint x="1705.0" y="100.0" />
        <di:waypoint x="1800.0" y="100.0" />
        <di:waypoint x="1830.0" y="100.0" />
        <di:waypoint x="1830.0" y="30.0" />
        <di:waypoint x="750.0" y="30.0" />
        <di:waypoint x="750.0" y="75.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_8" bpmnElement="round_Flow_8">
        <di:waypoint x="1990.0" y="135.0" />
        <di:waypoint x="1990.0" y="315.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_9" bpmnElement="round_Flow_9">
        <di:waypoint x="1965.0" y="340.0" />
        <di:waypoint x="1755.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_10" bpmnElement="round_Flow_10">
        <di:waypoint x="1990.0" y="365.0" />
        <di:waypoint x="1990.0" y="552.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_11" bpmnElement="round_Flow_11">
        <di:waypoint x="1605.0" y="340.0" />
        <di:waypoint x="1395.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_12" bpmnElement="round_Flow_12">
        <di:waypoint x="1345.0" y="340.0" />
        <di:waypoint x="1078.0" y="340.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_13" bpmnElement="round_Flow_13">
        <di:waypoint x="1370.0" y="365.0" />
        <di:waypoint x="1370.0" y="552.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_14" bpmnElement="round_Flow_14">
        <di:waypoint x="775.0" y="100.0" />
        <di:waypoint x="908.5" y="100.0" />
        <di:waypoint x="908.5" y="790.0" />
        <di:waypoint x="1042.0" y="790.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="round_DI_Flow_15" bpmnElement="round_Flow_15">
        <di:waypoint x="1078.0" y="790.0" />
        <di:waypoint x="1662.0" y="790.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="providers_DI_Pool_providers" bpmnElement="providers_Pool_providers" isHorizontal="true">
        <dc:Bounds x="0.0" y="1100.0" width="1220" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="providers_DI_Lane_worker" bpmnElement="providers_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="1100.0" width="1190" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="providers_DI_notice" bpmnElement="providers_notice">
        <dc:Bounds x="132.0" y="1182.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="providers_DI_choose" bpmnElement="providers_choose">
        <dc:Bounds x="365.0" y="1165.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="providers_DI_reply" bpmnElement="providers_reply">
        <dc:Bounds x="675.0" y="1165.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="providers_DI_end" bpmnElement="providers_end">
        <dc:Bounds x="1042.0" y="1182.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="providers_DI_Flow_0" bpmnElement="providers_Flow_0">
        <di:waypoint x="168.0" y="1200.0" />
        <di:waypoint x="365.0" y="1200.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="providers_DI_Flow_1" bpmnElement="providers_Flow_1">
        <di:waypoint x="515.0" y="1200.0" />
        <di:waypoint x="675.0" y="1200.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="providers_DI_Flow_2" bpmnElement="providers_Flow_2">
        <di:waypoint x="825.0" y="1200.0" />
        <di:waypoint x="1042.0" y="1200.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_service_pending_round_0" bpmnElement="Message_service_pending_round_0">
        <di:waypoint x="440" y="135" />
        <di:waypoint x="440" y="1000" />
        <di:waypoint x="150" y="1000" />
        <di:waypoint x="150" y="1182" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="180" y="970" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_service_pending_round_1" bpmnElement="Message_service_pending_round_1">
        <di:waypoint x="750" y="1235" />
        <di:waypoint x="2080" y="1235" />
        <di:waypoint x="2080" y="30" />
        <di:waypoint x="1060" y="30" />
        <di:waypoint x="1060" y="82" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="1730" y="1040" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Для PENDING код жёстко выбирает first_accept / parallel / одну попытку. Интервал и окно ответа равны SERVICE_REQUEST_PENDING_OFFER_TTL_SECONDS. Это отличается от настраиваемых стратегий ASSIGNED. Сообщение order.action.required предлагает accept/decline и popup_policy=fullscreen_offer; параметр popup не доказывает, что приложение показало окно человеку.

Ответ поступает напрямую через XMPP либо через доверенный web relay. Проверяются actor/JID, round/order/ticket/status, принадлежность участника, допустимое действие, offer id при наличии, срок и повтор. Первый допустимый accept даёт winner, все отрицательные — no_winner, истечение TTL — timed_out. Отклонённый/поздний/повторный ответ не является новым согласием. Квитанция order.action.response-result о приёме ответа ещё не подтверждает запись назначения.

handler-intents с HTTP 202 подтверждает передачу intent, а не изменение заказа. В проекте также зарегистрирован прямой пользовательский actions API с отдельными каноническими проверками: нельзя утверждать, что любой интерфейсный путь обязательно проходит этот раунд. Маршруты и различие описаны в TEMPLATE.

Повторные backend-проверки

accept-pending-provider под блокировкой актуального заказа требует PENDING и отсутствие текущего provider, существование кандидата, hard eligibility, отсутствие конфликтующего активного заказа и готовность обязательных проверок выбранного исполнителя. Подготовка requirements может создать недостающие действия и вернуть requirements_pending, не назначая исполнителя.

При успехе provider сохраняется и выполняется канонический переход ACCEPTED; неуспешный переход очищает только что назначенный provider. Этот action не повторяет буквально весь availability/online-фильтр подбора и не проверяет общий deadline: нельзя приписывать ему такие гарантии. Общий срок проверяет runtime.

Доменный отказ назначения оставляет winner для следующей попытки. Поэтому ожидание внешней проверки либо устойчивый конфликт победителя может удерживать ту же кандидатуру до устранения причины или наступления общего срока поиска. Ответы других кандидатов не заменяют её автоматически новым победителем.

Что получают остальные

После success или stale action runtime пытается отправить остальным участникам раунда response-result с кодом lost. Ошибка отдельного send логируется. Поскольку stale тоже запускает эту рассылку, само сообщение «заказ принял другой исполнитель» не является доказательством, какой provider записан в БД: проверяйте фактический Orders и Ticket.

При включённом SERVICE_REQUEST_PENDING_RECORD_OFFER_EVENTS могут записываться offer-события для доставленных send получателей. Регистрация попытки и успешный XMPP-send не доказывают прочтение/подтверждение приложением. Round registry, ответы и offer id остаются процессной памятью, без exactly-once гарантии.

Два разных срока

Срок Расчёт / действие
Общее окно ASAP-поиска time_placed + SERVICE_REQUEST_ASAP_SEARCH_MAX_SECONDS → попытка PRE_FORCEMAJEUER
Плановое начало подготовки planned_start − SERVICE_REQUEST_PRE_START_DURATION_SECONDS → попытка PRE_FORCEMAJEUER
Окно одной партии runtime now + SERVICE_REQUEST_PENDING_OFFER_TTL_SECONDS → timed_out, затем новая партия
Повтор при пустом списке / отказе winner SERVICE_REQUEST_PENDING_RECHECK_SECONDS

Точное техническое имя следующего статуса — PRE_FORCEMAJEUER. Это ещё не окончательный FORCEMAJEUR: дальнейшие действия принадлежат следующему handler. Narrow move проверяет текущий PENDING и отсутствие provider под lock; контроль даты выполняется до вызова в runtime, не повторяется этим backend action. Без/при некорректной контрольной дате timing-проверка не объявляет срок наступившим.

Диагностика и восстановление

Разделяйте отсутствие допустимых кандидатов, отсутствие JID, send failure, timeout, отклонение ответа и отказ backend назначить уже выбранного победителя. Для проверки нужны текущие Orders/Ticket/provider, timing context, cursor/cycle/round outcome, capabilities и ответ канонического action. Локальная причина provider_matching_batch сама по себе не доказывает успешную рассылку.

API 401/403/5xx и транспортные исключения не равны отказу человека и идут в processing_error с DEFERRED_TICKET_RECHECK_SECONDS. При 404 scope runtime освобождает устаревшее локальное состояние. После сохранённого перехода нового владельца будит ticket.changed, прежний получает ticket.moved; periodic reconciliation по INTERVAL_TIME_BD_REQ восстанавливает состав при потере события. Не исправляйте расхождение повторной ручной отправкой старого offer id.

Проверенные источники

Git SHA/SHA-256 и модели закреплены в metadata и BPMN. При анализе handler и бизнес-API не исполнялись. Сборщик повторно сверяет закреплённые Git-файлы; общий автоматический hook всех обновлений Wiki пока не завершён.

Связанные материалы

sharixopen/knowledge/scenarios/service_request_pending.1793220971.txt.gz · Последнее изменение: — sx_knowledge_api_open

© 2022 ShariX