EVENT_ROBOT_FLOW_DESIGN - zero1ne-26/doc GitHub Wiki
์ด๋ฒคํธ ๋ก๋ด ํ๋ก์ฐ (Event Robot Flow) ์ค๊ณ
์์ฑ์ผ: 2026-09-12 ยท ์ํ: 1์ฐจ ๊ตฌํ ์๋ฃ (orchestration-server ๋ง์ด๊ทธ๋ ์ด์ 118) โ ์๋ ยง7 "๊ตฌํ ๊ฒฐ์ " ์ฐธ๊ณ . ยง1~ยง6 ์ ์์. ยท ๊ด๋ จ: LOCATION_AUTOMATION_DESIGN, sequence, MQTT_SCHEMA-SPOT, MQTT_SCHEMA-ROBOT_ARM
๋ชฉํ ํ๋ก์ฐ (๋งํธ ์ ์ฌ):
sequenceDiagram oc_server-->>MQTT: mqtt.pub run_scenario market_load MQTT-->>Spot: sub robot/spot-01/command Spot->>Spot: ๋งํธ๋ก ์ด๋ ยท ์์ธ ๋ณ๊ฒฝ Spot-->>MQTT: pub ack SUCCESS MQTT-->>oc_server: SPOT ์์ ์๋ฃ oc_server-->>MQTT: mqtt.pub pick_basket MQTT-->>๋ก๋ดํ: sub robot/arm-01/command ๋ก๋ดํ->>๋ก๋ดํ: ๋ฌผ๊ฑด ์ง๊ธฐ ๋ก๋ดํ-->>MQTT: pub ack SUCCESS MQTT-->>oc_server: ๋ก๋ดํ ์์ ์๋ฃ oc_server-->>MQTT: mqtt.pub navigate_to (๋ค์ ์ฅ์) MQTT-->>Spot: sub navigate_to Spot-->>MQTT: pub ack SUCCESS MQTT-->>oc_server: ํ์คํฌ ์๋ฃ ์ฒ๋ฆฌ
1. ๊ฒฐ๋ก ๋จผ์
์ ์คํ ์์ง์ ๋ง๋ค์ง ์๋๋ค. ์ ํ๋ก์ฐ๋ ์ด๋ฏธ ์๋ ์๋ํ ๊ท์น(arrival_automations) ์ ์ก์
์ฒด์ธ
๊ทธ๋๋ก๋ค โ ๊ท์น ํ๋์ ์ก์
์ spot run_scenario โ robot_arm pick_basket โ spot navigate_to ์์๋ก ๋ฃ์ผ๋ฉด
๋๋ฐ์ด์ค ํ๊ฐ ์ ์ก์
์ ์ข
๊ฒฐ ack(SUCCESS/FAULT)๋ฅผ ๊ธฐ๋ค๋ฆฐ ๋ค ๋ค์ ์ก์
์ ๋ฐํํ๋ค(ยง4.3 ๋๋ฐ์ด์ค ๋ช
๋ น ํ).
sequence ์ ์ฑ
2ยท3ยท5(๋์ฐฉ ์๋ฃ ํ ์ง์, ์ ์ฌ ์ค SPOT ์ ์ง)๋ ์ด ์ฒด์ธ ๊ตฌ์กฐ์์ ์๋์ผ๋ก ์ง์ผ์ง๋ค.
์ด๋ฒคํธ ๋๋ฉ์ธ์์ ๋น ์ง ๊ฒ์ ๋ค ๊ฐ์ง๋ฟ์ด๊ณ , ์ด ์ค๊ณ๋ ๊ทธ ๋ค ๊ฐ์ง๋ง ์ถ๊ฐํ๋ค.
| # | ๋น ์ง ๊ฒ | ์ถ๊ฐ |
|---|---|---|
| A | ์ด๋ฒคํธ ๊ท์น์ ํธ๋ฆฌ๊ฑฐ๊ฐ ์ฅ์ ๋์ฐฉ๋ฟ โ ํ์ ์ด ๋จ๊ฑฐ๋ ๊ด๋๊ฐ์ด ์ ํ์ง๋ฅผ ๊ณ ๋ฅธ ์๊ฐ์ ํ๋ก์ฐ๋ฅผ ์์ํ ์ ์์ | ํธ๋ฆฌ๊ฑฐ event_published, option_selected ์ถ๊ฐ |
| B | ํ๋ก์ฐ๊ฐ ๋๋๋ ํ์คํฌ ์๋ฃ๋ก ์ด์ด์ง์ง ์์ (ํ์คํฌ ์์ ๊ท์น๋ง user_task_commands ๋ก ์ถ์ ํด ์๋ ์๋ฃ) | ๊ท์น์ "์๋ฃ ์ฒ๋ฆฌํ ํ์คํฌ" ์ง์ โ ์ฒด์ธ ์ ์ฒด๋ฅผ ๊ทธ ํ์คํฌ ๋ช ๋ น์ผ๋ก ์ถ์ , ์ ๋ถ ์ข ๊ฒฐ๋๋ฉด ์๋ completed |
| C | ์ ์ก์ ์ด ์คํจํด๋ ๋ค์ ์ก์ ์ด ๋๊ฐ (SPOT ์ด๋ ์คํจ โ ๋ก๋ดํ์ด ๋น์๋ฆฌ์์ ์์ , ์ ์ฑ 3 ์๋ฐ) | ์ก์
๋ณ stop_on_failure (์คํจ ์ ์ฒด์ธ ์ค๋จ) |
| D | ์ด๋ฒคํธ ์ ํ์ง์ ๋ก๋ด ์ฐ๋์ด ๋จ์ผ SPOT ๋ช ๋ น + ๋ฐ๋ ค๋ก๋ด + LG ์ ์๋ฟ์ด๋ผ ๋ค๋จ๊ณ ํํ ๋ถ๊ฐ | ์ ํ์ง๋ ๊ทธ๋๋ก ๋๊ณ , ๋ค๋จ๊ณ๋ option_selected ๊ท์น์ผ๋ก ์ฎ๊ธด๋ค (์ ํ์ง ํธ์ง๊ธฐ์ "ํ๋ก์ฐ๋ก ์ฐ๊ฒฐ" ์๋ด) |
2. ๋ฐ์ดํฐ ๋ชจ๋ธ ๋ณ๊ฒฝ (๋ง์ด๊ทธ๋ ์ด์ 118)
-- ํธ๋ฆฌ๊ฑฐ ํ์ฅ
ALTER TABLE arrival_automations DROP CONSTRAINT arrival_automations_trigger_check;
ALTER TABLE arrival_automations ADD CONSTRAINT arrival_automations_trigger_check
CHECK (trigger IN ('arrive','leave','wrong_item','right_item','event_published','option_selected'));
-- B. ์๋ฃ ์ฒ๋ฆฌํ ํ์คํฌ
ALTER TABLE arrival_automations ADD COLUMN complete_task_mode TEXT NOT NULL DEFAULT 'none'
CHECK (complete_task_mode IN ('none','task_id','location_task'));
ALTER TABLE arrival_automations ADD COLUMN complete_task_id TEXT; -- mode='task_id' ์ผ ๋ tasks.id
-- C. ์คํจ ์ ์ฒด์ธ ์ค๋จ
ALTER TABLE arrival_automation_actions ADD COLUMN stop_on_failure BIGINT NOT NULL DEFAULT 0 CHECK (stop_on_failure IN (0,1));
event_published/option_selected๋ ์ด๋ฒคํธ ์์ ๊ท์น ์ ์ฉ(์ด๋๋ฏผ ๊ฒ์ฆ).option_selected๋condition_json.option_ids: []๋ก ์ด๋ ์ ํ์ง์ ๋ฐ์ํ ์ง ๊ณ ๋ฅธ๋ค(๋น๋ฉด ๋ชจ๋ ์ ํ์ง).complete_task_modetask_id: ์ง์ ํ์คํฌ(complete_task_id). ๋งํธ ์ด๋ฒคํธ ํ๋ก์ฐ๊ฐ "๋งํธ ์ฅ๋ณด๊ธฐ" ํ์คํฌ๋ฅผ ์๋ฃ์ํค๋ ๊ธฐ๋ณธํ.location_task: ๊ท์น์ด ์คํ๋๋ ์ฅ์(์ด๋ฒคํธ๊ฐ ๋งคํ๋ user_location)์์ ์ด ์ธ์ ์ ๋ฏธ์๋ฃ ํ์คํฌ ์ ๋ถ. ํ์คํฌ ID ๋ฅผ ํ๋์ฝ๋ฉํ์ง ์์๋ ๋์ง๋ง ์ฅ์์ ๋ฏธ์๋ฃ ํ์คํฌ๊ฐ ์ฌ๋ฟ์ด๋ฉด ๋ค ์๋ฃ๋ผ ๋ฒ๋ฆฌ๋ฏ๋ก ๊ธฐ๋ณธ๊ฐ์task_id.- ํ์คํฌ ์์ ๊ท์น์ ์ง๊ธ์ฒ๋ผ ์๊ธฐ ํ์คํฌ๋ฅผ ์ถ์ ํ๋ค(๊ธฐ์กด ๋์ ์ ์ง, ์ปฌ๋ผ์
none).
- ๊ธฐ์กด ํ์ ์ ๋ถ ๊ธฐ๋ณธ๊ฐ์ด๋ผ ๋์์ด ๋ฐ๋์ง ์๋๋ค.
stop_on_failure=0์ด ํ์ฌ ๋์(์คํจํด๋ ๊ณ์).
3. ์๋ฒ ์คํ ํ๋ฆ
3.1 ํธ๋ฆฌ๊ฑฐ ํ (์ ๊ท 2๊ฐ)
event_timing.go publishSelectedEvent(...) ์งํ โ onEventPublished(userID, eventID, locationID)
event_option_select.go ์ ํ์ง ์ฒ๋ฆฌ ์งํ โ onOptionSelected(userID, eventID, optionID, locationID)
(locationID = GetUserLocationByUserAndEvent)
๋ ๋ค ArrivalAutomationEngine.Run(RunArrivalParams{Trigger, TriggerEventID, TriggerOptionID, LocationID}) ๋ฅผ goroutine ์ผ๋ก
ํธ์ถํ๋ค. ํ๋ณด ๊ท์น์ owner_type='event' AND owner_id=eventID AND trigger=? (์ ๊ท ์ฟผ๋ฆฌ ListActiveAutomationsByEventTrigger).
option_selected ๋ evaluateRule ์์ condition.option_ids ๋ฅผ ๊ฒ์ฌํ๋ค.
๋ฐํ ์ ์ฑ ยท์กฐ๊ฑดยท์ฟจ๋ค์ดยท์คํ ๋ก๊ทธ(automation_runs)๋ ๋์ฐฉ ๊ท์น๊ณผ ๋์ผ. ์ํ ๋ฐํ(๋ฐฑ์คํผ์ค)์ ์ด๋ฒคํธ ํ ์คํธ ํจ๋์ "์๋ํ ๊ฐ์ ์คํ"์ ํธ๋ฆฌ๊ฑฐ์ ๋ฌด๊ดํ๊ฒ ๊ท์น์ ์ง์ ์คํํ๋ค(๊ธฐ์กด Manual ๊ฒฝ๋ก).
3.2 ์ก์ ์ฒด์ธ = ํ๋ก์ฐ
dispatchActions ๋ ์ง๊ธ์ฒ๋ผ ์ก์
์ Next ์ฒด์ธ์ผ๋ก ๋ฌถ๋๋ค. ๋ชฉํ ํ๋ก์ฐ๋ ๊ท์น ํ๋:
| ์์ | device | action | params | stop_on_failure |
|---|---|---|---|---|
| 1 | spot | run_scenario | {scenario_id:"market_load"} |
1 |
| 2 | robot_arm | pick_basket | {basket:1} |
1 |
| 3 | spot | navigate_to | {destination_mode:"next_location"} |
0 |
- 1โ2: SPOT ์ข ๊ฒฐ ack(SUCCESS) ๋ฅผ ํ๊ฐ ๊ธฐ๋ค๋ฆฐ ๋ค ๋ก๋ดํ ๋ฐํ โ sequence ์ ์ฑ 2.
- 2 ์งํ ์ค SPOT ํ๋ ๋น์ด ์๊ณ ์๋ฒ๋ SPOT ์ ์๋ฌด๊ฒ๋ ๋ณด๋ด์ง ์๋๋ค โ ์ ์ฑ 5.
- 3:
next_location์ ๋งคํ ์ฅ์ ๊ธฐ์ค ๋ค์ ๋ฐฉ๋ฌธ ์ฅ์(GetNextUserLocationAfter). ์ด๋ฒคํธ ๊ท์น์ LocationID ๋ ๋งคํ ์ฅ์์ด๋ฏ๋ก ๊ทธ๋๋ก ๋์. - ๋ก๋ดํ ํ์์์์ ์ด๋ฏธ 120์ด ๊ธฐ๋ณธ, SPOT run_scenario ๋
REJECTED๋ ์ข ๊ฒฐ๋ก ์จ๋ค๋ ์คํค๋ง ์์ธ(MQTT_SCHEMA-SPOT ยง4)๋ฅผ isTerminalSpotStatus ์ ๋ฐ์ํด์ผ ํ๋ค โ ํ์ฌ REJECTED ๋ ๋น์ข ๊ฒฐ๋ก ์ทจ๊ธํด run_scenario ๊ฐ ์คํ ์คํจ๋ก REJECTED ๋ฅผ ๋ณด๋ด๋ฉด ํ๊ฐ ํ์์์๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.ACCEPTED ์ดํ์ REJECTED๋ง ์ข ๊ฒฐ๋ก ๋ณด๋๋ก ์์ (ยง6-1).
3.3 ์คํจ ์ ์ค๋จ (C)
device_queue handle() ์ข
๋ฃ ์ finalActionStatus(res) ๊ฐ failed/timeout ์ด๊ณ job.StopOnFailure ๋ฉด enqueueNext ๋ฅผ ๊ฑด๋๋ฐ๊ณ ,
๋จ์ ์ฒด์ธ(Next/NextGroup ์ฌ๊ท)์ ์ก์
๊ฒฐ๊ณผ๋ฅผ skipped / chain_stopped ๋ก automation_runs ์ ๊ธฐ๋ก, ์ถ์ ์ค์ธ ํ์คํฌ ๋ช
๋ น๋
failed / chain_stopped ๋ก ๋ซ๋๋ค(ํ์คํฌ๊ฐ ์๋ ์๋ฃ๋์ง ์๋๋ก โ ์๋ 3.4).
3.4 ํ์คํฌ ์๋ฃ (B)
- ๊ท์น ์คํ ์
complete_task_mode์ ๋ฐ๋ผ ์ถ์ ํ์คํฌ ID ๋ชฉ๋ก์ ์ ํ๊ณ , ์ฒด์ธ์ ๋ชจ๋ ์ก์recordTaskCommands๋ก ๋จ๊ธด๋ค (ํ์คํฌ ์์ ๊ท์น๊ณผ ๊ฐ์ ๊ฒฝ๋ก,rule_id๋ก ์ด๋ค ๊ท์น์ด ๋ง๋ ๋ช ๋ น์ธ์ง ๊ตฌ๋ถ). - ๋ชจ๋ ๋ช
๋ น์ด ์ข
๊ฒฐ๋๋ฉด
finishTaskCommand๊ฐProcessTaskCompletion์ ํธ์ถ โ ๊ฒฐ์ ํ์: ์ง๊ธ์ ์คํจ ๋ช ๋ น์ด ์์ฌ๋ "์ ๋ถ ์ข ๊ฒฐ"์ด๋ฉด ์๋ฃ ์ฒ๋ฆฌํ๋ค. ํ๋ก์ฐ์์๋stop_on_failure๋ก ์ค๋จ๋ ๊ฒฝ์ฐ ์๋ฃ์ํค์ง ์๋ ํธ์ด ๋ง์ผ๋ฏ๋ก, chain_stopped ๋ก ๋ซํ ๋ช ๋ น์ด ํ๋๋ผ๋ ์์ผ๋ฉด ์๋ฃ ๋์ ์ํ๋ฅผ ์ ์งํ๊ณ ๋ฐฑ์คํผ์ค ์ฌ์ฉ์ ์์ธ์ "ํ๋ก์ฐ ์ค๋จ" ๋ฐฐ์ง๋ฅผ ๋์ด๋ค. - ์๋ฃ๋๋ฉด ๊ธฐ์กด๋๋ก ๋์๋ณด๋ ์ฌ๋ฐํ ยท ํฌ์ธํธ ยท ์์ฐจ ์คํ ํ์(117) ยท ์ด๋ฒคํธ ํ์ด๋ฐ ํ๋จ์ด ์ด์ด์ง๋ค.
3.5 ์ ํ์ง์์ ๊ด๊ณ (D)
- ์ ํ์ง์ ๊ธฐ์กด ๋จ์ผ ๋ช ๋ น(spot_action/companion/lg)์ ์ ์งํ๋ค(ํธํ).
- ๊ฐ์ ์ ํ์ง์
option_selected๊ท์น์ด ์์ผ๋ฉด ์ ํ์ง์ spot_action ์ ๋น์ ๋๋ผ๊ณ ํธ์ง๊ธฐ๊ฐ ๊ฒฝ๊ณ ํ๋ค(์ด์ค ๋ฐํ ๋ฐฉ์ง). ์๋ฒ๋ ๊ท์น์ด ๋งค์นญ๋๋ฉด ์ ํ์ง์ spot_action ์ ๊ฑด๋๋ฐ๋๋ก ์ต์ ํํ ์ ์์ผ๋, 1์ฐจ๋ ๊ฒฝ๊ณ ๋ง. - ๋ฐ๋ ค๋ก๋ด ๋ฐํ(์ ํ ์งํ "์ค์ด ๋๋ฆด๊ฒ์")๋ ๊ท์น์ ์ฒซ ์ก์ ์ companion say(parallel) ๋ก ๋ฃ์ผ๋ฉด SPOT ๊ณผ ๋์์ ๋๊ฐ๋ค(100 ๋ณ๋ ฌ ๊ทธ๋ฃน).
4. ๋ฐฑ์คํผ์ค
- ์ด๋ฒคํธ ์์ธ โ ์๋ํ ํธ์ง๊ธฐ: ํธ๋ฆฌ๊ฑฐ ๋๋กญ๋ค์ด์
๐ฃ ํ์ ์ด ๋ฐํ๋์ ๋,โ๏ธ ์ ํ์ง๋ฅผ ๊ณจ๋์ ๋(์ ํ์ง ๋ค์ค ์ ํ ์นฉ) ์ถ๊ฐ. ๊ท์น ํผ์ "์๋ฃ ์ฒ๋ฆฌํ ํ์คํฌ" (์์ / ํ์คํฌ ์ ํ / ๋งคํ ์ฅ์์ ํ์คํฌ) ์ถ๊ฐ. ์ก์ ์นด๋์ "์คํจ ์ ์ฒด์ธ ์ค๋จ" ์ฒดํฌ. - ์ก์ ์์ ์์ ์ํ์ค ๋ค์ด์ด๊ทธ๋จ ๋ฏธ๋ฆฌ๋ณด๊ธฐ(AutomationSequenceDiagram ์ฌ์ฌ์ฉ)๋ก ์ mermaid ์ ๊ฐ์ ๊ทธ๋ฆผ์ ๋ณด์ฌ์ค๋ค.
- ์ด๋ฒคํธ ํ
์คํธ ํจ๋(์ค๋ ์ถ๊ฐํ ๊ฒ)์ "์ ํ์ง ์ ํ ์๋ฎฌ๋ ์ด์
" ๋ฒํผ: ํ๋ธ๋ฆฟ์
event/option/select์ ๊ฐ์ ๊ฒฝ๋ก๋ฅผ ํ์ option_selected ํ๋ก์ฐ๋ฅผ ๋๊น์ง ๊ฒ์ฆํ๋ค. ๊ฒฐ๊ณผ ํ์๋ ๊ท์น๋ณ ์ก์ ์ํ์ ํ์คํฌ ์๋ฃ ์ฌ๋ถ๊ฐ ์ด์ด์ ๋ณด์ธ๋ค. - ์คํ ๋ก๊ทธ(/automations/runs)์ ์ฌ์ฉ์ ์์ธ ๋ช
๋ น ํ๋ ๊ทธ๋๋ก ์ฐ๋
chain_stopped์ฌ์ ๋ผ๋ฒจ ์ถ๊ฐ.
5. ๊ตฌํ ์์ (์์ 4๋จ๊ณ, ์๋ฒ โ ๋ฐฑ์คํผ์ค)
- ๋ง์ด๊ทธ๋ ์ด์ 118 + ์ฟผ๋ฆฌ(์๊ธฐ sqlc) + ์ด๋๋ฏผ ๊ฒ์ฆ(ํธ๋ฆฌ๊ฑฐ/complete_task/stop_on_failure)
- ์์ง: ํธ๋ฆฌ๊ฑฐ ํ 2๊ฐ, option_ids ์กฐ๊ฑด, complete_task ์ถ์ , stop_on_failure ์ค๋จ + chain_stopped ๊ธฐ๋ก, run_scenario REJECTED ์ข ๊ฒฐ ์ฒ๋ฆฌ
- ๋ฐฑ์คํผ์ค ํธ์ง๊ธฐ(ํธ๋ฆฌ๊ฑฐยท์๋ฃ ํ์คํฌยท์ค๋จ ์ฒดํฌยท๋ค์ด์ด๊ทธ๋จ) + ํ ์คํธ ํจ๋ ์ ํ์ง ์๋ฎฌ๋ ์ด์
- ์ํค: ์ด ๋ฌธ์๋ฅผ "๊ตฌํ"์ผ๋ก ๊ฐฑ์ , MQTT_SCHEMA-ORCHESTRATION_SERVER 24๋ฒ์ ํธ๋ฆฌ๊ฑฐ ์ถ๊ฐ
6. ๊ฒฐ์ ์ด ํ์ํ ๊ฒ
- run_scenario ์ REJECTED ์ข ๊ฒฐ ์ฒ๋ฆฌ โ SPOT ํ ์คํค๋ง๋๋ก "ACCEPTED ๋ค์ ์จ REJECTED ๋ ์ข ๊ฒฐ"๋ก ๋ฐ๊พผ๋ค. ๋ค๋ฅธ ์ก์ ์๋ ์ํฅ ์์(ACCEPTED ์ REJECTED ๋ ์ฌ์ ํ ์๋ฃ ์๋ต ์์). ๋ฐ๋ ์๊ฒฌ ์์ผ๋ฉด ์งํ.
- ์คํจ ์์ธ ํ๋ก์ฐ์ ํ์คํฌ ์๋ฃ โ 3.4 ์ ์(์ค๋จ๋๋ฉด ์๋ฃ ์ ํจ)์ผ๋ก ๊ฐ์ง, ์ง๊ธ์ฒ๋ผ ์ ๋ถ ์ข ๊ฒฐ์ด๋ฉด ์๋ฃ๋ก ๋ณผ์ง.
- ํธ๋ฆฌ๊ฑฐ ๊ธฐ๋ณธ๊ฐ โ ๋งํธ ํ๋ก์ฐ๋ฅผ
option_selected(๊ด๋๊ฐ์ด "์ค์ด์ค" ์ ํ) ๋ก ํ ์งevent_published(ํ์ ๋จ์๋ง์) ๋ก ํ ์ง. ์์ฐ ํต์ ์ธก๋ฉด์์๋option_selected๋ฅผ ๊ถ์ฅํ๋ค(์ฌ๋์ด ์์ ์์ ์ ์ฅ๋ค). location_task๋ชจ๋๊ฐ ํ์ํ์ง โ ์์ผ๋ฉดtask_id๋ง ๋๊ณ ๋จ์ํ.
7. ๊ตฌํ ๊ฒฐ์ (2026-09-12)
์์ A~D ์ค ์ฌ์ฉ์ ๊ฒฐ์ ์ ๋ฐ๋ผ ๋ค์๊ณผ ๊ฐ์ด ๊ตฌํํ๋ค.
| ์์ | ๊ฒฐ์ | ๊ตฌํ |
|---|---|---|
| A ํธ๋ฆฌ๊ฑฐ | ํ์ ๋ฒํผ ํด๋ฆญ๋ง | trigger='option_selected' (์ด๋ฒคํธ ์์ ๊ท์น ์ ์ฉ). event_published ๋ ๋ง๋ค์ง ์์ |
| B ํ์คํฌ ์๋ฃ | ์์ โ ์ด๋ฒคํธ ๋๋ฉ์ธ์๋ ์๋ฃ ๊ฐ๋ ์ด ์๋ค | complete_task_* ์ปฌ๋ผ ์์. ์ด๋ฒคํธ ๊ท์น์ user_task_commands ๋ก ์ถ์ ํ์ง ์๋๋ค |
| C ์คํจ ์ ์ค๋จ | ๋ณด๋ฅ โ ์คํจํ๋ฉด ์ต๊ทผ ์ด๋ ฅ์ผ๋ก ํ์ธ | stop_on_failure ์์(์คํจํด๋ ๋ค์ ๋จ๊ณ ์งํ, ๊ธฐ์กด ๋์). ์ด๋ฒคํธ ์์ธ ํ์ดํ๋ผ์ธ ์นด๋์ "์ต๊ทผ ์ด๋ ฅ"์์ ๋จ๊ณ๋ณ ์ํยท์๋ฌ ํ์ธ |
| D ์ ํ์ง ๋ค๋จ๊ณ | ์ ์ด๋ฒคํธ ํ์
pipeline |
ํ์
์ choice ์ฒ๋ผ ๋ฒํผ ํ์. ๋ฒํผ๋ง๋ค ํ์ดํ๋ผ์ธ(๊ท์น 1๊ฐ = condition.option_ids=[๋ฒํผ], ์ก์
= ๋จ๊ณ)์ "๋จ๊ณ ์ถ๊ฐ"๋ก ์๋๋ค. pipeline ์ด๋ฒคํธ๋ ์ ํ์ง์ ๋จ์ผ SPOT/๋ฐ๋ ค๋ก๋ด/LG ๋ช
๋ น์ ์ฐ์ง ์๋๋ค(ํธ์ง ๋ชจ๋ฌ์์ ์จ๊น, ์๋ฒ๋ ๊ฑด๋๋) |
- ์๋ฒ:
ProcessEventOptionSelect(MQTT ํธ๋ค๋ฌยทํ ์คํธ ํจ๋ ๊ณต์ฉ) โ pipeline ์ด๋ฒคํธ๋ฉดonOptionSelectedโRun(Trigger=option_selected, TriggerEventID, TriggerOptionID)โ ๊ท์น์ ์ก์ ์ฒด์ธ์ ๋๋ฐ์ด์ค ํ์ ์ ์ฌ(์ ๋จ๊ณ ์ข ๊ฒฐ ack ๋๊ธฐ). ์๋ต{ok:true, status:"pipeline_queued"}. - ๋ฐฑ์คํผ์ค: ์ด๋ฒคํธ ํ์ "๋ก๋ด ํ์ดํ๋ผ์ธ" โ "๋ฒํผ(์ ํ์ง)" ์นด๋ + "๐ ํ์ดํ๋ผ์ธ" ์นด๋(๋ฒํผ๋ณ ๋จ๊ณ ํธ์ง, ์ํ์ค ๋ค์ด์ด๊ทธ๋จ, ์ต๊ทผ ์ด๋ ฅ). ์ด๋ฒคํธ ํ ์คํธ ํจ๋์ "๋ฒํผ ์ ํ ์๋ฎฌ๋ ์ด์ "(๊ฐ์ ์ธ์ ์ผ๋ก ์ข ๋จ ๊ฒ์ฆ).
๋ฏธํด๊ฒฐ(ยง6-1)ํด๊ฒฐ(2026-09-21): SPOTREJECTEDยทBUSY๋ฅผ ์ข ๊ฒฐ(์คํจ)๋ก ์ฒ๋ฆฌ โ ์๋ฃ ์๋ต์ด ์ค์ง ์๋ โ ๋จ๊ณ ๊ฑฐ์ ์ด๋ผ ์ฆ์ ์คํจ๋ก ๋๋ด๊ณ ๋ค์ ๋ช ๋ น์ผ๋ก ๋์ด๊ฐ๋ค(์ข ์ ์ 30์ด ํ์์์์ ์ฑ์ฐ๋ฉฐ ํ๊ฐ ๋ฐ๋ ธ์).fault_detail์ด ์คํจ ์ฌ์ (์:CHARGING)๋ก ๋จ๋๋ค.
8. ์คํจ ์ ๋ฉ์ถค(๊ธฐ๋ณธ) + ์ด๋๋ฏผ ์๋ ์ฌ์๋ (2026-09-19, ๋ง์ด๊ทธ๋ ์ด์ 126ยท127, ๊ธฐ๋ณธํ 128)
ยง7-C ์์ ๋ณด๋ฅํ๋ ์คํจ ์ ์ฑ
์ ์ฒซ ์กฐ๊ฐ. "๋ก๋ดํ ๋ช
๋ น์ด ์คํจํด๋ SPOT ์ด ๋น์๋ฆฌ๋ก ๊ฐ ๋ฒ๋ฆฌ๋" ๋ฌธ์ ๋ฅผ ๋ง๋๋ค.
์ฌ์๋๋ ์๋ ๋ฐ๋ณต์ด ์๋๋ผ ์ด๋๋ฏผ์ด ๋ฐฑ์คํผ์ค์์ ์ง์ ๋๋ฅธ๋ค (126 ์์ ์ ๊น ๋ฃ์๋ ์๋ ๋ฐ๋ณตยทautomation_retry_max_attempts ๋ 127 ์์ ํ๊ธฐ).
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ๊ธฐ๋ณธ ๋์ (128, 2026-09-19) | ๋ชจ๋ ์ก์
์ด ์คํจ ์ ๋ฉ์ถค. ์ตํธ์ธ ์ฒดํฌ(_hold_on_failure)๋ ์ค์ ์ด์์์ ๋ก๋ดํ FAULT ๋ค SPOT ์ด ๊ทธ๋๋ก ์ถ๋ฐํ ์ฌ๊ณ ๋ก ํ๊ธฐ. ์์ธ์ ์ผ๋ก "์คํจํด๋ ๋ค์ ๋จ๊ณ ์งํ"์ด ํ์ํ ์ก์
(์ฐ์ถ์ฉ ๋ฐํ ๋ฑ)๋ง ์นด๋์ "โถ ์คํจํด๋ ๋ค์ ๋จ๊ณ ์งํ" ์ฒดํฌ โ params_json._continue_on_failure=true. ๋๋ฐ์ด์ค๋ก ๋๊ฐ๋ params ์์๋ ์๋ฒ๊ฐ ์ ๊ฑฐ(popFailurePolicy) |
| ๊ธฐ๋ค๋ฆฌ์ง ์๋ ๋จ๊ณ (2026-10-04) | ์นด๋์ "๋ค ๋จ๊ณ๊ฐ ๊ธฐ๋ค๋ฆฌ์ง ์์" ์ฒดํฌ โ params_json._no_wait=true. ๊ฐ์ด ์ถ๋ฐํ๋ ๋ค ๋จ๊ณ๊ฐ ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๋๋ค(๋๋ก ๋ฐฐ์ก ๋ฑ). ์ฒด์ธ์ ๋งค๋ฌ๋ ค ์์ง ์์ผ๋ฏ๋ก ์คํจํด๋ ๋ฉ์ถ ๊ฒ์ด ์๋ค โ hold_on_failure=false, awaiting_retry ๋ฅผ ๋ฌ์ง ์๋๋ค. ์์ธํ ๊ท์น์ LOCATION_AUTOMATION_DESIGN 9-1 |
| ๋์ | ํ ์๋น์(device_queue.go handle)๊ฐ ์ข
๊ฒฐ ๊ฒฐ๊ณผ๊ฐ ์๋ฃ๊ฐ ์๋๋ฉด(๊ฑฐ์ ยทFAULT_*ยทtimeoutยทdispatch ์ค๋ฅ) ๊ฒฐ๊ณผ๋ฅผ failed/timeout ์ผ๋ก ๋จ๊ธฐ๋ Next ์ฒด์ธ์ ์ ์ฌํ์ง ์๋๋ค โ ๋ค ๋จ๊ณ(SPOT)๋ queued ์ธ ์ฑ ๋ฉ์ถค. ๋ณ๋ ฌ ๊ทธ๋ฃน์ ํ ์ก์ด ๋ฉ์ถ๋ฉด ๊ทธ๋ฃน ์ ์ฒด์ ๋ค์ ๋จ๊ณ๋ ๋๊ฐ์ง ์๋๋ค(heldGroups). _continue_on_failure ์ก์
๋ง ์คํจํด๋ ๋ค์ ๋จ๊ณ ์งํ |
| ์คํ ๋ก๊ทธ | action_results[].hold_on_failure, awaiting_retry=true(๋ฉ์ถฐ์ ํด๋ฆญ์ ๊ธฐ๋ค๋ฆฌ๋ ๋จ๊ณ), attempts(์๋ ์ฌ์๋ ํ์). command_id ๋ ์ต์ ์๋ ๊ฒ |
| ์๋ ์ฌ์๋ | POST /api/admin/automations/runs/{runId}/retry {action_id} โ RetryRunFrom: ๊ทธ ๋จ๊ณ๋ถํฐ ๊ท์น์ ๋๋จธ์ง ์ก์
์ ๋ถ๋ฅผ ์ command_id ๋ก ๋ค์ ์ฒด์ธ ์ ์ฌ(๊ฐ์ run ์ ๊ฒฐ๊ณผ ๋ฎ์ด์ฐ๊ธฐ, attempts ์ด์ด ์ธ๊ธฐ). ๋จ, _no_wait ๋จ๊ณ๋ ๊ทธ ๋จ๊ณ๋ง ๋ค์ ๋ณด๋ธ๋ค โ ๋ค ๋จ๊ณ๋ ์ ์ด์ ์ด ๋จ๊ณ๋ฅผ ๊ธฐ๋ค๋ฆฐ ์ ์ด ์๋ค (2026-10-04). ์คํจ/ํ์์์ ๋จ๊ณ์๋ง ํ์ฉ(์๋๋ฉด 409). ํ์คํฌ ์ถ์ ์คํ์ด๋ฉด ๋์ด์๋ ๋จ๊ณ์ ์ user_task_commands ํ์ superseded ๋ก ๋ซ์ ์๋ ์๋ฃ ํ์ ์ด ์ ํ๋ง ๋ณด๊ฒ ํ๋ค |
| ๋ฒํผ ์์น | ์ด๋ฒคํธ ์์ธ ํ์ดํ๋ผ์ธ ์นด๋ ์คํ ์ด๋ ฅ(๋จ๊ณ๋ณ ๋ก๊ทธ ์) ยท ์๋ํ ์คํ ๋ก๊ทธ ํ์ด์ง ยท ์ฌ์ฉ์ ์์ธ ํ์คํฌ ์นด๋์ ์คํ ๋ก๊ทธ ยท ํ์คํฌ/์ด๋ฒคํธ ํ ์คํธ ํจ๋. ์คํจ/ํ์์์ ๋จ๊ณ์๋ง ๋ํ๋๋ค |
| ์ข ๊ฒฐ ์กฐ๊ฑด | SPOT REJECTEDยทBUSY ๋ ์ข
๊ฒฐ(์คํจ, 2026-09-21). ๋ฉ์ถค์ ์ข
๊ฒฐ(timeout ํฌํจ) ๋ค์ ๊ฑธ๋ฆฐ๋ค |