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

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


sharixopen:knowledge:scenarios:st_request_reopened

Повторно открытая ST_REQUEST: ожидание назначения

Назначение: Сценарий процесса. Продукт: ShariX Open.

Для кого: Разработчик · Поддержка · Рецензент и приёмщик · Нейросеть.

Темы: Обработчики → ST_REQUEST · Обработчики → Runtime.

Область: ShariX Open. Обработчик: open_st_request_reopened, тип ST_REQUEST (1), рабочий статус REOPENED (110). 31.10.2026 исходники повторно получены из Git: обе Python-копии совпали с новой канонической генерацией Blockly, проверены 11 исходников генераторов. Сам handler не исполнялся. Выбранная серверная версия, её настройки и работающие API/XMPP проверяются отдельно.

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

Вход — уже переоткрытое обращение. Обработчик:

  • ждёт повторного назначения;
  • не выбирает человека и не заполняет assigned_to;
  • не переводит Ticket в ASSIGNED самостоятельно;
  • не возобновляет автоматически исполнение содержания заявки.

STREQ_AUTOACCEPT в этой ветви не используется.

Для профильной проверки само переоткрытие не создаёт:

  • новую попытку RequirementCheck;
  • новую редакцию документа;
  • очистку прежнего verification_runtime.completed.

Повторное подтверждение оформляют с учётом доменной попытки и редакции. Прохождение старого Ticket ещё раз не гарантирует нового результата. Граница marker описана в DONE и WONTFIX.

Проход и локальное ожидание (BPMN)

Схема BPMN

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

Исходник схемы
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:ns2="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:ns3="http://www.omg.org/spec/DD/20100524/DC" xmlns:ns4="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_st_reopened_logic" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="reopened_Process_reopened" name="open_st_request_reopened: ожидание внешнего решения" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованная встроенная реализация; не доказательство выбранной версии на сервере.", "Процесс isExecutable=false, никакой handler при генерации не исполняется.", "deferred_until — символ локального срока, не имя параметра окружения."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_reopened.py", "repository": "sharix-open-handlers-examples", "sha256": "3a90597fd04397c49f5c801ce2a37a882bcc17269768d90e59db5121359f327d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_reopened.json", "repository": "sharix-open-handlers-examples", "sha256": "09edcb4f5451c480c96ce22822e5cd22dd158db0d7e30189dab947d7ba0df77a"}, {"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": "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": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}]}</bpmn:documentation>
    <bpmn:laneSet id="reopened_Lanes_reopened">
      <bpmn:lane id="reopened_Lane_worker" name="Worker: один проход Python">
        <bpmn:flowNodeRef>reopened_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_status</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_reason</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_defer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_cleanup</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_defer_error</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_error</bpmn:flowNodeRef>
      </bpmn:lane>
      <bpmn:lane id="reopened_Lane_queue" name="Планировщик: между проходами">
        <bpmn:flowNodeRef>reopened_wait</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_timer</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_revision</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>reopened_ready</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="reopened_start" name="Ticket готов к проходу">
      <bpmn:outgoing>reopened_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:exclusiveGateway id="reopened_status" name="Статус REOPENED?">
      <bpmn:incoming>reopened_Flow_0</bpmn:incoming>
      <bpmn:incoming>reopened_Flow_12</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_1</bpmn:outgoing>
      <bpmn:outgoing>reopened_Flow_2</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="reopened_reason" name="Записать support_reassignment">
      <bpmn:incoming>reopened_Flow_1</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="reopened_defer" name="Назначить повтор по настройке">
      <bpmn:documentation>ST_REQUEST_REOPENED_RECHECK_SECONDS; пустой аргумент reason использует сохранённую локальную причину.</bpmn:documentation>
      <bpmn:incoming>reopened_Flow_4</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_5</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:serviceTask id="reopened_cleanup" name="Убрать Ticket и удалить комнату">
      <bpmn:incoming>reopened_Flow_2</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_3</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:endEvent id="reopened_end" name="Текущий владелец освобождён">
      <bpmn:incoming>reopened_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:boundaryEvent id="reopened_defer_error" name="Неожиданная ошибка" attachedToRef="reopened_defer" cancelActivity="true">
      <bpmn:outgoing>reopened_Flow_6</bpmn:outgoing>
      <bpmn:errorEventDefinition />
    </bpmn:boundaryEvent>
    <bpmn:serviceTask id="reopened_error" name="processing_error + общий defer">
      <bpmn:documentation>DEFERRED_TICKET_RECHECK_SECONDS</bpmn:documentation>
      <bpmn:incoming>reopened_Flow_6</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_7</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:eventBasedGateway id="reopened_wait" name="Что наступило раньше?">
      <bpmn:incoming>reopened_Flow_5</bpmn:incoming>
      <bpmn:incoming>reopened_Flow_7</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_8</bpmn:outgoing>
      <bpmn:outgoing>reopened_Flow_9</bpmn:outgoing>
    </bpmn:eventBasedGateway>
    <bpmn:intermediateCatchEvent id="reopened_timer" name="Наступил срок defer">
      <bpmn:incoming>reopened_Flow_8</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_10</bpmn:outgoing>
      <bpmn:timerEventDefinition>
        <bpmn:timeDate xsi:type="bpmn:tFormalExpression">deferred_until</bpmn:timeDate>
      </bpmn:timerEventDefinition>
    </bpmn:intermediateCatchEvent>
    <bpmn:intermediateCatchEvent id="reopened_revision" name="Получена новая ревизия Ticket">
      <bpmn:incoming>reopened_Flow_9</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_11</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:intermediateCatchEvent>
    <bpmn:serviceTask id="reopened_ready" name="Снять defer, вернуть в ready FIFO">
      <bpmn:documentation>Дубликат ревизии не снимает defer; при новом статусе очистка в следующем проходе/по ticket.moved.</bpmn:documentation>
      <bpmn:incoming>reopened_Flow_10</bpmn:incoming>
      <bpmn:incoming>reopened_Flow_11</bpmn:incoming>
      <bpmn:outgoing>reopened_Flow_12</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sequenceFlow id="reopened_Flow_0" sourceRef="reopened_start" targetRef="reopened_status" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_1" sourceRef="reopened_status" targetRef="reopened_reason" name="Да" />
    <bpmn:sequenceFlow id="reopened_Flow_2" sourceRef="reopened_status" targetRef="reopened_cleanup" name="Нет" />
    <bpmn:sequenceFlow id="reopened_Flow_3" sourceRef="reopened_cleanup" targetRef="reopened_end" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_4" sourceRef="reopened_reason" targetRef="reopened_defer" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_5" sourceRef="reopened_defer" targetRef="reopened_wait" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_6" sourceRef="reopened_defer_error" targetRef="reopened_error" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_7" sourceRef="reopened_error" targetRef="reopened_wait" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_8" sourceRef="reopened_wait" targetRef="reopened_timer" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_9" sourceRef="reopened_wait" targetRef="reopened_revision" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_10" sourceRef="reopened_timer" targetRef="reopened_ready" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_11" sourceRef="reopened_revision" targetRef="reopened_ready" name="" />
    <bpmn:sequenceFlow id="reopened_Flow_12" sourceRef="reopened_ready" targetRef="reopened_status" name="Следующий проход" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_st_reopened_logic">
    <bpmn:participant id="reopened_Pool_reopened" name="open_st_request_reopened: ожидание внешнего решения" processRef="reopened_Process_reopened" />
  </bpmn:collaboration>
  <ns2:BPMNDiagram id="Diagram_st_reopened_logic">
    <ns2:BPMNPlane id="Plane_st_reopened_logic" bpmnElement="Collaboration_st_reopened_logic">
      <ns2:BPMNShape id="reopened_DI_Pool_reopened" bpmnElement="reopened_Pool_reopened" isHorizontal="true">
        <ns3:Bounds x="0.0" y="0.0" width="1690.0" height="770.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_Lane_worker" bpmnElement="reopened_Lane_worker" isHorizontal="true">
        <ns3:Bounds x="30.0" y="0.0" width="1660.0" height="385.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_Lane_queue" bpmnElement="reopened_Lane_queue" isHorizontal="true">
        <ns3:Bounds x="30.0" y="385.0" width="1660.0" height="385.0" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_start" bpmnElement="reopened_start">
        <ns3:Bounds x="132.0" y="92.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_status" bpmnElement="reopened_status">
        <ns3:Bounds x="365.0" y="85.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_reason" bpmnElement="reopened_reason">
        <ns3:Bounds x="575.0" y="75.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_defer" bpmnElement="reopened_defer">
        <ns3:Bounds x="835.0" y="75.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_cleanup" bpmnElement="reopened_cleanup">
        <ns3:Bounds x="315.0" y="265.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_end" bpmnElement="reopened_end">
        <ns3:Bounds x="632.0" y="282.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_defer_error" bpmnElement="reopened_defer_error">
        <ns3:Bounds x="942.0" y="127.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_error" bpmnElement="reopened_error">
        <ns3:Bounds x="1095.0" y="265.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_wait" bpmnElement="reopened_wait">
        <ns3:Bounds x="885.0" y="515.0" width="50" height="50" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_timer" bpmnElement="reopened_timer">
        <ns3:Bounds x="1152.0" y="452.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_revision" bpmnElement="reopened_revision">
        <ns3:Bounds x="1152.0" y="652.0" width="36" height="36" />
      </ns2:BPMNShape>
      <ns2:BPMNShape id="reopened_DI_ready" bpmnElement="reopened_ready">
        <ns3:Bounds x="1355.0" y="505.0" width="150" height="70" />
      </ns2:BPMNShape>
      <ns2:BPMNEdge id="reopened_DI_Flow_0" bpmnElement="reopened_Flow_0">
        <ns4:waypoint x="168.0" y="110.0" />
        <ns4:waypoint x="365.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_1" bpmnElement="reopened_Flow_1">
        <ns4:waypoint x="415.0" y="110.0" />
        <ns4:waypoint x="575.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_2" bpmnElement="reopened_Flow_2">
        <ns4:waypoint x="390.0" y="135.0" />
        <ns4:waypoint x="390.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_3" bpmnElement="reopened_Flow_3">
        <ns4:waypoint x="465.0" y="300.0" />
        <ns4:waypoint x="632.0" y="300.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_4" bpmnElement="reopened_Flow_4">
        <ns4:waypoint x="725.0" y="110.0" />
        <ns4:waypoint x="835.0" y="110.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_5" bpmnElement="reopened_Flow_5">
        <ns4:waypoint x="910.0" y="145.0" />
        <ns4:waypoint x="910.0" y="515.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_6" bpmnElement="reopened_Flow_6">
        <ns4:waypoint x="978.0" y="145.0" />
        <ns4:waypoint x="1020.0" y="145.0" />
        <ns4:waypoint x="1170.0" y="145.0" />
        <ns4:waypoint x="1170.0" y="265.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_7" bpmnElement="reopened_Flow_7">
        <ns4:waypoint x="1245.0" y="300.0" />
        <ns4:waypoint x="1290.0" y="300.0" />
        <ns4:waypoint x="1290.0" y="410.0" />
        <ns4:waypoint x="910.0" y="410.0" />
        <ns4:waypoint x="910.0" y="515.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_8" bpmnElement="reopened_Flow_8">
        <ns4:waypoint x="935.0" y="540.0" />
        <ns4:waypoint x="1043.5" y="540.0" />
        <ns4:waypoint x="1043.5" y="470.0" />
        <ns4:waypoint x="1152.0" y="470.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_9" bpmnElement="reopened_Flow_9">
        <ns4:waypoint x="935.0" y="540.0" />
        <ns4:waypoint x="1043.5" y="540.0" />
        <ns4:waypoint x="1043.5" y="670.0" />
        <ns4:waypoint x="1152.0" y="670.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_10" bpmnElement="reopened_Flow_10">
        <ns4:waypoint x="1188.0" y="470.0" />
        <ns4:waypoint x="1271.5" y="470.0" />
        <ns4:waypoint x="1271.5" y="540.0" />
        <ns4:waypoint x="1355.0" y="540.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_11" bpmnElement="reopened_Flow_11">
        <ns4:waypoint x="1188.0" y="670.0" />
        <ns4:waypoint x="1271.5" y="670.0" />
        <ns4:waypoint x="1271.5" y="540.0" />
        <ns4:waypoint x="1355.0" y="540.0" />
      </ns2:BPMNEdge>
      <ns2:BPMNEdge id="reopened_DI_Flow_12" bpmnElement="reopened_Flow_12">
        <ns4:waypoint x="1505.0" y="540.0" />
        <ns4:waypoint x="1650.0" y="540.0" />
        <ns4:waypoint x="1650.0" y="25.0" />
        <ns4:waypoint x="390.0" y="25.0" />
        <ns4:waypoint x="390.0" y="85.0" />
        <ns2:BPMNLabel>
          <ns3:Bounds x="1330.0" y="5.0" width="180" height="26" />
        </ns2:BPMNLabel>
      </ns2:BPMNEdge>
    </ns2:BPMNPlane>
  </ns2:BPMNDiagram>
</bpmn:definitions>

Один проход в своём рабочем статусе:

  1. Записать локальную причину support_reassignment.
  2. Назначить defer по ST_REQUEST_REOPENED_RECHECK_SECONDS. Пустой reason использует ранее сохранённую причину.
  3. Завершить проход и освободить worker.

Причина относится к runtime и журналу. Она не добавляет комментарий в Ticket и не уведомляет пользователя.

Worker после прохода освобождается. Когда срок deferred_until наступает либо получена новая authoritative revision, Ticket становится готов к повторной проверке; одинаковый снимок не сбрасывает ожидание. Фактический запуск зависит от свободного worker и соединения XMPP. Defer хранится в памяти; после рестарта состав очереди сверяется с backend заново.

При чужом статусе запрашивается удаление локального Ticket и комнаты. Одного возврата None недостаточно для удаления: runtime учитывает явный запрос очистки. Неожиданное исключение обрабатывается общим processing_error с defer по DEFERRED_TICKET_RECHECK_SECONDS; автоматическое бизнес-решение вместо пользователя не принимается.

Внешний пользователь и смена владельца (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_st_reopened_external" targetNamespace="urn:sharix:knowledge:handlers">
  <bpmn:process id="person_Process_person" name="Пользователь с доступом к Ticket и правом смены статуса" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованная встроенная реализация; не доказательство выбранной версии на сервере.", "Процесс isExecutable=false, никакой handler при генерации не исполняется.", "deferred_until — символ локального срока, не имя параметра окружения.", "Изменение статуса и best-effort XMPP доставка — отдельные операции. При потере события есть periodic reconciliation."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_reopened.py", "repository": "sharix-open-handlers-examples", "sha256": "3a90597fd04397c49f5c801ce2a37a882bcc17269768d90e59db5121359f327d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_reopened.json", "repository": "sharix-open-handlers-examples", "sha256": "09edcb4f5451c480c96ce22822e5cd22dd158db0d7e30189dab947d7ba0df77a"}, {"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": "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": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}]}</bpmn:documentation>
    <bpmn:laneSet id="person_Lanes_person">
      <bpmn:lane id="person_Lane_worker" name="Осмысленное решение по карточке">
        <bpmn:flowNodeRef>person_start</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>person_choose</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>person_send</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>person_end</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="person_start" name="Решение по обращению">
      <bpmn:outgoing>person_Flow_0</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:userTask id="person_choose" name="Выбрать ASSIGNED / WONTFIX / DUPLICATE">
      <bpmn:incoming>person_Flow_0</bpmn:incoming>
      <bpmn:outgoing>person_Flow_1</bpmn:outgoing>
    </bpmn:userTask>
    <bpmn:sendTask id="person_send" name="Отправить смену статуса">
      <bpmn:incoming>person_Flow_1</bpmn:incoming>
      <bpmn:outgoing>person_Flow_2</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="person_end" name="Действие отправлено">
      <bpmn:incoming>person_Flow_2</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="person_Flow_0" sourceRef="person_start" targetRef="person_choose" name="" />
    <bpmn:sequenceFlow id="person_Flow_1" sourceRef="person_choose" targetRef="person_send" name="" />
    <bpmn:sequenceFlow id="person_Flow_2" sourceRef="person_send" targetRef="person_end" name="" />
  </bpmn:process>
  <bpmn:process id="backend_Process_backend" name="Tickets backend: объектный доступ, переход и commit" isExecutable="false">
    <bpmn:documentation>{"notes": ["Опубликованная встроенная реализация; не доказательство выбранной версии на сервере.", "Процесс isExecutable=false, никакой handler при генерации не исполняется.", "deferred_until — символ локального срока, не имя параметра окружения.", "Изменение статуса и best-effort XMPP доставка — отдельные операции. При потере события есть periodic reconciliation."], "sources": [{"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "handlers/open_st_request_reopened.py", "repository": "sharix-open-handlers-examples", "sha256": "3a90597fd04397c49f5c801ce2a37a882bcc17269768d90e59db5121359f327d"}, {"commit": "76e0c693b628ed4a1fa34515a3f8abdff26149bb", "path": "generated_handler_blocks/open_st_request_reopened.json", "repository": "sharix-open-handlers-examples", "sha256": "09edcb4f5451c480c96ce22822e5cd22dd158db0d7e30189dab947d7ba0df77a"}, {"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": "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": "utils.py", "repository": "sharix-open-tickets", "sha256": "a5680205c6522e1d9a74d9d267fe9ee96faf6f06436b00877fc0a93d80234bf5"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "views/ticket_detail.py", "repository": "sharix-open-tickets", "sha256": "05d344b0fba14cf895400694d4a18f486c800fef08dd1acb43ea46909b9e7e59"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "api/views/handler_workflow.py", "repository": "sharix-open-tickets", "sha256": "f97c4b467a9a30749f5c4b86b39a833c430e57aaa1f030f70030d9b5c609d368"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "signals.py", "repository": "sharix-open-tickets", "sha256": "39aad8690a2e7d35cebfb052127a8130a951cbb4eea316c4f767a0a59fc5fa7e"}, {"commit": "fd64704d7d9f01a5ec5b7b89cbc5afe5102b2c14", "path": "services/handler_wakeup.py", "repository": "sharix-open-tickets", "sha256": "c9fdc62a18301fd7c075395c697d5b1c738c77713aa71fcbb5ab097e173d98de"}]}</bpmn:documentation>
    <bpmn:laneSet id="backend_Lanes_backend">
      <bpmn:lane id="backend_Lane_worker" name="Сохранение состояния">
        <bpmn:flowNodeRef>backend_request</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_acl</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_allowed</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_commit</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_publish</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_end</bpmn:flowNodeRef>
        <bpmn:flowNodeRef>backend_reject</bpmn:flowNodeRef>
      </bpmn:lane>
    </bpmn:laneSet>
    <bpmn:startEvent id="backend_request" name="Запрос из карточки/API">
      <bpmn:outgoing>backend_Flow_0</bpmn:outgoing>
      <bpmn:messageEventDefinition />
    </bpmn:startEvent>
    <bpmn:serviceTask id="backend_acl" name="Проверить права и переход lifecycle">
      <bpmn:incoming>backend_Flow_0</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_1</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:exclusiveGateway id="backend_allowed" name="Разрешено?">
      <bpmn:incoming>backend_Flow_1</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_2</bpmn:outgoing>
      <bpmn:outgoing>backend_Flow_3</bpmn:outgoing>
    </bpmn:exclusiveGateway>
    <bpmn:serviceTask id="backend_commit" name="Сохранить статус и Event">
      <bpmn:incoming>backend_Flow_2</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_4</bpmn:outgoing>
    </bpmn:serviceTask>
    <bpmn:sendTask id="backend_publish" name="После commit: смена владельца">
      <bpmn:incoming>backend_Flow_4</bpmn:incoming>
      <bpmn:outgoing>backend_Flow_5</bpmn:outgoing>
    </bpmn:sendTask>
    <bpmn:endEvent id="backend_end" name="Статус сохранён">
      <bpmn:incoming>backend_Flow_5</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:endEvent id="backend_reject" name="Отказ: переход не выполнен">
      <bpmn:incoming>backend_Flow_3</bpmn:incoming>
    </bpmn:endEvent>
    <bpmn:sequenceFlow id="backend_Flow_0" sourceRef="backend_request" targetRef="backend_acl" name="" />
    <bpmn:sequenceFlow id="backend_Flow_1" sourceRef="backend_acl" targetRef="backend_allowed" name="" />
    <bpmn:sequenceFlow id="backend_Flow_2" sourceRef="backend_allowed" targetRef="backend_commit" name="Да" />
    <bpmn:sequenceFlow id="backend_Flow_3" sourceRef="backend_allowed" targetRef="backend_reject" name="Нет" />
    <bpmn:sequenceFlow id="backend_Flow_4" sourceRef="backend_commit" targetRef="backend_publish" name="" />
    <bpmn:sequenceFlow id="backend_Flow_5" sourceRef="backend_publish" targetRef="backend_end" name="" />
  </bpmn:process>
  <bpmn:collaboration id="Collaboration_st_reopened_external">
    <bpmn:participant id="person_Pool_person" name="Пользователь с доступом к Ticket и правом смены статуса" processRef="person_Process_person" />
    <bpmn:participant id="backend_Pool_backend" name="Tickets backend: объектный доступ, переход и commit" processRef="backend_Process_backend" />
    <bpmn:participant id="old_Participant" name="open_st_request_reopened: исключить локальный снимок и комнату" />
    <bpmn:participant id="next_Participant" name="Новый владелец: ASSIGNED / WONTFIX / DUPLICATE" />
    <bpmn:messageFlow id="Message_st_reopened_external_0" sourceRef="person_send" targetRef="backend_request" name="Запрос перехода" />
    <bpmn:messageFlow id="Message_st_reopened_external_1" sourceRef="backend_publish" targetRef="old_Participant" name="ticket.moved: прежний REOPENED" />
    <bpmn:messageFlow id="Message_st_reopened_external_2" sourceRef="backend_publish" targetRef="next_Participant" name="ticket.changed: новый владелец" />
  </bpmn:collaboration>
  <bpmndi:BPMNDiagram id="Diagram_st_reopened_external">
    <bpmndi:BPMNPlane id="Plane_st_reopened_external" bpmnElement="Collaboration_st_reopened_external">
      <bpmndi:BPMNShape id="person_DI_Pool_person" bpmnElement="person_Pool_person" isHorizontal="true">
        <dc:Bounds x="0.0" y="0.0" width="1100" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="person_DI_Lane_worker" bpmnElement="person_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="0.0" width="1070" height="200" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="person_DI_start" bpmnElement="person_start">
        <dc:Bounds x="132.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="person_DI_choose" bpmnElement="person_choose">
        <dc:Bounds x="345.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="person_DI_send" bpmnElement="person_send">
        <dc:Bounds x="625.0" y="65.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="person_DI_end" bpmnElement="person_end">
        <dc:Bounds x="922.0" y="82.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="person_DI_Flow_0" bpmnElement="person_Flow_0">
        <di:waypoint x="168.0" y="100.0" />
        <di:waypoint x="345.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="person_DI_Flow_1" bpmnElement="person_Flow_1">
        <di:waypoint x="495.0" y="100.0" />
        <di:waypoint x="625.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="person_DI_Flow_2" bpmnElement="person_Flow_2">
        <di:waypoint x="775.0" y="100.0" />
        <di:waypoint x="922.0" y="100.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="backend_DI_Pool_backend" bpmnElement="backend_Pool_backend" isHorizontal="true">
        <dc:Bounds x="0.0" y="270.0" width="1630" height="380" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_Lane_worker" bpmnElement="backend_Lane_worker" isHorizontal="true">
        <dc:Bounds x="30.0" y="270.0" width="1600" height="380" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_request" bpmnElement="backend_request">
        <dc:Bounds x="132.0" y="352.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_acl" bpmnElement="backend_acl">
        <dc:Bounds x="345.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_allowed" bpmnElement="backend_allowed">
        <dc:Bounds x="675.0" y="345.0" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_commit" bpmnElement="backend_commit">
        <dc:Bounds x="875.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_publish" bpmnElement="backend_publish">
        <dc:Bounds x="1145.0" y="335.0" width="150" height="70" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_end" bpmnElement="backend_end">
        <dc:Bounds x="1452.0" y="352.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="backend_DI_reject" bpmnElement="backend_reject">
        <dc:Bounds x="682.0" y="532.0" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="backend_DI_Flow_0" bpmnElement="backend_Flow_0">
        <di:waypoint x="168.0" y="370.0" />
        <di:waypoint x="345.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_1" bpmnElement="backend_Flow_1">
        <di:waypoint x="495.0" y="370.0" />
        <di:waypoint x="675.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_2" bpmnElement="backend_Flow_2">
        <di:waypoint x="725.0" y="370.0" />
        <di:waypoint x="875.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_3" bpmnElement="backend_Flow_3">
        <di:waypoint x="700.0" y="395.0" />
        <di:waypoint x="700.0" y="532.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_4" bpmnElement="backend_Flow_4">
        <di:waypoint x="1025.0" y="370.0" />
        <di:waypoint x="1145.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="backend_DI_Flow_5" bpmnElement="backend_Flow_5">
        <di:waypoint x="1295.0" y="370.0" />
        <di:waypoint x="1452.0" y="370.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="DI_old_Participant" bpmnElement="old_Participant" isHorizontal="true">
        <dc:Bounds x="0" y="800" width="760" height="100" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="DI_next_Participant" bpmnElement="next_Participant" isHorizontal="true">
        <dc:Bounds x="850" y="800" width="850" height="100" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="DI_Message_st_reopened_external_0" bpmnElement="Message_st_reopened_external_0">
        <di:waypoint x="700" y="135" />
        <di:waypoint x="700" y="225" />
        <di:waypoint x="150" y="225" />
        <di:waypoint x="150" y="352" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="250" y="195" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_reopened_external_1" bpmnElement="Message_st_reopened_external_1">
        <di:waypoint x="1220" y="405" />
        <di:waypoint x="1220" y="630" />
        <di:waypoint x="380" y="630" />
        <di:waypoint x="380" y="800" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="230" y="680" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="DI_Message_st_reopened_external_2" bpmnElement="Message_st_reopened_external_2">
        <di:waypoint x="1280" y="405" />
        <di:waypoint x="1650" y="405" />
        <di:waypoint x="1650" y="700" />
        <di:waypoint x="1275" y="700" />
        <di:waypoint x="1275" y="800" />
        <bpmndi:BPMNLabel>
          <dc:Bounds x="1100" y="735" width="260" height="42" />
        </bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>

Для внешнего решения проверяются отдельно:

  • право чтения конкретного Ticket;
  • право менять его статус;
  • разрешённый переход текущего lifecycle;
  • доменная граница: связанный заказ должен изменяться через действия заказа.

Авторство обращения само по себе не даёт права смены статуса.

Из REOPENED допустимы:

  • ASSIGNED: вернуть обращение на стадию назначения; выбранного человека проверить отдельно.
  • WONTFIX: зафиксировать отказ от выполнения, далее действует соответствующий сценарий.
  • DUPLICATE: признать обращение дубликатом, далее действует сценарий ожидания закрытия.

Переход в ASSIGNED сам по себе не заполняет assigned_to. Handler REOPENED не выбирает исход за пользователя.

После commit backend направляет:

  • ticket.moved прежнему handler: локальный снимок исключается; для выполняющегося worker удаление откладывается до завершения прохода.
  • ticket.changed новому зарегистрированному handler: новое состояние ставится в его очередь.

У CLOSED нет отдельного open_st_request_closed в каталоге. Сохранение статуса и доставка события — разные операции.

XMPP-доставка best effort и не является частью транзакции сохранения Ticket. Потерю сообщения восстанавливает scoped periodic reconciliation по INTERVAL_TIME_BD_REQ. Успешный список без Ticket позволяет убрать прежний снимок; ошибка списка не должна трактоваться как пустая очередь. Новый локальный проход не заменяет проверку актуального backend-состояния.

Настройки и диагностика

Именованный интервал — ST_REQUEST_REOPENED_RECHECK_SECONDS, минимум одна секунда; реальное значение конкретного сервера здесь не предполагается. Обработчик не содержит фиксированного срока автоматического закрытия. Для общего восстановления используется DEFERRED_TICKET_RECHECK_SECONDS, для сверки состава — INTERVAL_TIME_BD_REQ.

Порядок диагностики долгого ожидания:

  1. Прочитать актуальные статус и ревизию Ticket.
  2. Сверить выбранные Python/workspace с канонической генерацией.
  3. Проверить именованный интервал, локальную причину и момент готовности defer.
  4. Проверить доступность внешнего действия и права принимающего решение.
  5. Проверить scoped API, ready-очередь, XMPP и periodic reconciliation.

Повтор таймера без изменения статуса штатен, пока внешнее решение не принято. Неопределённый ответ записи требует чтения сохранённого состояния перед повтором.

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

Алгоритм извлечён узким адаптером известной структуры Blockly и сверен реальным renderer с Python. Неизвестная структура или изменение изученных runtime/ACL-источников блокируют такую генерацию до повторного анализа. Это авторский инструмент для двух известных observer-сценариев, не общий автоматический hook обновления Wiki.

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

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

© 2022 ShariX