[{"data":1,"prerenderedAt":2421},["ShallowReactive",2],{"docs:\u002Fko\u002Fguide\u002Fflow":3},{"page":4,"untranslated":2420,"translated":78},{"id":5,"title":6,"body":7,"description":2411,"extension":2412,"meta":2413,"navigation":78,"path":2414,"publishedAt":2415,"seo":2416,"stem":2417,"updatedAt":2418,"__hash__":2419},"docs_ko\u002Fko\u002Fguide\u002Fflow.md","Flow",{"type":8,"value":9,"toc":2393},"minimark",[10,14,22,27,41,402,420,452,456,493,529,532,570,573,615,630,634,640,794,819,838,841,850,1042,1060,1085,1099,1103,1114,1118,1127,1185,1392,1427,1444,1517,1521,1546,1633,1641,1645,1672,1703,1711,1715,1738,1741,1744,1821,1834,1854,1865,1869,1893,1897,1905,1911,1915,1924,2060,2097,2100,2112,2124,2144,2148,2156,2303,2319,2359,2389],[11,12,6],"h1",{"id":13},"flow",[15,16,17,18,21],"p",{},"Flow는 의존 관계를 가진 여러 작업을 유향 비순환 그래프(DAG)로 정의하는 구조입니다.",[19,20],"br",{},"\nRun은 Flow를 1회 실행한 단위입니다.",[23,24,26],"h2",{"id":25},"定義","정의",[15,28,29,33,34,37,38,40],{},[30,31,32],"code",{},"createFlow","는 ",[30,35,36],{},"performers","를 받아 Flow를 정의하는 함수를 반환합니다.",[19,39],{},"\nbinding 이름과 payload의 타입은 단독 작업과 마찬가지로 타입 검사를 받습니다.",[42,43,48],"pre",{"className":44,"code":45,"language":46,"meta":47,"style":47},"language-ts shiki shiki-themes github-light github-dark","import { createFlow, defineTsumugi } from 'tsumugi';\n\nconst performers = { ListNames, Greet, Report };\nconst flow = createFlow(performers);\n\nconst flows = {\n  GREETINGS: flow\u003C{ prefix: string }>((f) => {\n    const list = f.node('list', 'ListNames', {\n      input: (i) => ({ prefix: i.prefix }),\n    });\n\n    const each = f.fanOut('greet', 'Greet', {\n      after: { list },\n      over: (_i, d) => d.list.names,\n      input: (name) => ({ name }),\n    });\n\n    f.node('report', 'Report', {\n      after: { each },\n      input: (_i, d) => ({ total: d.each.total, failed: d.each.failed }),\n    });\n  }),\n};\n\nconst tsumugi = defineTsumugi({ performers, flows, auth: \u002F* ... *\u002F });\n","ts","",[30,49,50,73,80,96,113,118,131,166,198,217,223,228,255,261,284,301,306,311,331,337,357,362,368,374,379],{"__ignoreMap":47},[51,52,55,59,63,66,70],"span",{"class":53,"line":54},"line",1,[51,56,58],{"class":57},"szBVR","import",[51,60,62],{"class":61},"sVt8B"," { createFlow, defineTsumugi } ",[51,64,65],{"class":57},"from",[51,67,69],{"class":68},"sZZnC"," 'tsumugi'",[51,71,72],{"class":61},";\n",[51,74,76],{"class":53,"line":75},2,[51,77,79],{"emptyLinePlaceholder":78},true,"\n",[51,81,83,86,90,93],{"class":53,"line":82},3,[51,84,85],{"class":57},"const",[51,87,89],{"class":88},"sj4cs"," performers",[51,91,92],{"class":57}," =",[51,94,95],{"class":61}," { ListNames, Greet, Report };\n",[51,97,99,101,104,106,110],{"class":53,"line":98},4,[51,100,85],{"class":57},[51,102,103],{"class":88}," flow",[51,105,92],{"class":57},[51,107,109],{"class":108},"sScJk"," createFlow",[51,111,112],{"class":61},"(performers);\n",[51,114,116],{"class":53,"line":115},5,[51,117,79],{"emptyLinePlaceholder":78},[51,119,121,123,126,128],{"class":53,"line":120},6,[51,122,85],{"class":57},[51,124,125],{"class":88}," flows",[51,127,92],{"class":57},[51,129,130],{"class":61}," {\n",[51,132,134,137,139,142,146,149,152,155,158,161,164],{"class":53,"line":133},7,[51,135,136],{"class":61},"  GREETINGS: ",[51,138,13],{"class":108},[51,140,141],{"class":61},"\u003C{ ",[51,143,145],{"class":144},"s4XuR","prefix",[51,147,148],{"class":57},":",[51,150,151],{"class":88}," string",[51,153,154],{"class":61}," }>((",[51,156,157],{"class":144},"f",[51,159,160],{"class":61},") ",[51,162,163],{"class":57},"=>",[51,165,130],{"class":61},[51,167,169,172,175,177,180,183,186,189,192,195],{"class":53,"line":168},8,[51,170,171],{"class":57},"    const",[51,173,174],{"class":88}," list",[51,176,92],{"class":57},[51,178,179],{"class":61}," f.",[51,181,182],{"class":108},"node",[51,184,185],{"class":61},"(",[51,187,188],{"class":68},"'list'",[51,190,191],{"class":61},", ",[51,193,194],{"class":68},"'ListNames'",[51,196,197],{"class":61},", {\n",[51,199,201,204,207,210,212,214],{"class":53,"line":200},9,[51,202,203],{"class":108},"      input",[51,205,206],{"class":61},": (",[51,208,209],{"class":144},"i",[51,211,160],{"class":61},[51,213,163],{"class":57},[51,215,216],{"class":61}," ({ prefix: i.prefix }),\n",[51,218,220],{"class":53,"line":219},10,[51,221,222],{"class":61},"    });\n",[51,224,226],{"class":53,"line":225},11,[51,227,79],{"emptyLinePlaceholder":78},[51,229,231,233,236,238,240,243,245,248,250,253],{"class":53,"line":230},12,[51,232,171],{"class":57},[51,234,235],{"class":88}," each",[51,237,92],{"class":57},[51,239,179],{"class":61},[51,241,242],{"class":108},"fanOut",[51,244,185],{"class":61},[51,246,247],{"class":68},"'greet'",[51,249,191],{"class":61},[51,251,252],{"class":68},"'Greet'",[51,254,197],{"class":61},[51,256,258],{"class":53,"line":257},13,[51,259,260],{"class":61},"      after: { list },\n",[51,262,264,267,269,272,274,277,279,281],{"class":53,"line":263},14,[51,265,266],{"class":108},"      over",[51,268,206],{"class":61},[51,270,271],{"class":144},"_i",[51,273,191],{"class":61},[51,275,276],{"class":144},"d",[51,278,160],{"class":61},[51,280,163],{"class":57},[51,282,283],{"class":61}," d.list.names,\n",[51,285,287,289,291,294,296,298],{"class":53,"line":286},15,[51,288,203],{"class":108},[51,290,206],{"class":61},[51,292,293],{"class":144},"name",[51,295,160],{"class":61},[51,297,163],{"class":57},[51,299,300],{"class":61}," ({ name }),\n",[51,302,304],{"class":53,"line":303},16,[51,305,222],{"class":61},[51,307,309],{"class":53,"line":308},17,[51,310,79],{"emptyLinePlaceholder":78},[51,312,314,317,319,321,324,326,329],{"class":53,"line":313},18,[51,315,316],{"class":61},"    f.",[51,318,182],{"class":108},[51,320,185],{"class":61},[51,322,323],{"class":68},"'report'",[51,325,191],{"class":61},[51,327,328],{"class":68},"'Report'",[51,330,197],{"class":61},[51,332,334],{"class":53,"line":333},19,[51,335,336],{"class":61},"      after: { each },\n",[51,338,340,342,344,346,348,350,352,354],{"class":53,"line":339},20,[51,341,203],{"class":108},[51,343,206],{"class":61},[51,345,271],{"class":144},[51,347,191],{"class":61},[51,349,276],{"class":144},[51,351,160],{"class":61},[51,353,163],{"class":57},[51,355,356],{"class":61}," ({ total: d.each.total, failed: d.each.failed }),\n",[51,358,360],{"class":53,"line":359},21,[51,361,222],{"class":61},[51,363,365],{"class":53,"line":364},22,[51,366,367],{"class":61},"  }),\n",[51,369,371],{"class":53,"line":370},23,[51,372,373],{"class":61},"};\n",[51,375,377],{"class":53,"line":376},24,[51,378,79],{"emptyLinePlaceholder":78},[51,380,382,384,387,389,392,395,399],{"class":53,"line":381},25,[51,383,85],{"class":57},[51,385,386],{"class":88}," tsumugi",[51,388,92],{"class":57},[51,390,391],{"class":108}," defineTsumugi",[51,393,394],{"class":61},"({ performers, flows, auth: ",[51,396,398],{"class":397},"sJ8bj","\u002F* ... *\u002F",[51,400,401],{"class":61}," });\n",[15,403,404,407,408,410,411,416,417,419],{},[30,405,406],{},"f.node","의 첫 번째 인자에는 node ID를, 두 번째 인자에는 binding 이름을 지정합니다.",[19,409],{},"\nbinding 이름은 ",[412,413,415],"a",{"href":414},"\u002Fko\u002Fguide\u002Fperformer#binding%E5%90%8D","export한 이름","과 일치시켜야 합니다.",[19,418],{},"\nnode ID는 영숫자, 하이픈, 언더스코어로 구성합니다.",[15,421,422,425,426,428,429,432,433,435,436,191,439,191,442,191,445,191,448,451],{},[30,423,424],{},"input","에는 Flow의 입력과 앞 단계의 반환값으로 payload를 생성하는 함수를 지정합니다.",[19,427],{},"\n두 번째 인자는 ",[30,430,431],{},"after","에 전달한 객체의 키를 프로퍼티 이름으로 가지는 객체입니다.",[19,434],{},"\nnode 정의에는 작업을 enqueue할 때와 같은 옵션(",[30,437,438],{},"maxAttempts",[30,440,441],{},"backoff",[30,443,444],{},"timeoutMs",[30,446,447],{},"priority",[30,449,450],{},"concurrencyKey"," 등)을 선택적으로 지정할 수 있습니다.",[23,453,455],{"id":454},"開始","시작",[42,457,459],{"className":44,"code":458,"language":46,"meta":47,"style":47},"const runId = await tsumugi.start(env, 'GREETINGS', { prefix: 'hello' });\n",[30,460,461],{"__ignoreMap":47},[51,462,463,465,468,470,473,476,479,482,485,488,491],{"class":53,"line":54},[51,464,85],{"class":57},[51,466,467],{"class":88}," runId",[51,469,92],{"class":57},[51,471,472],{"class":57}," await",[51,474,475],{"class":61}," tsumugi.",[51,477,478],{"class":108},"start",[51,480,481],{"class":61},"(env, ",[51,483,484],{"class":68},"'GREETINGS'",[51,486,487],{"class":61},", { prefix: ",[51,489,490],{"class":68},"'hello'",[51,492,401],{"class":61},[15,494,495,497,498,500,502,503,506,507,510,511,513,514,516,517,519,520,523,524,528],{},[30,496,424],{},"의 타입은 Flow의 타입 인자에서 도출됩니다.",[19,499],{},[30,501,478],{},"의 네 번째 인자로 ",[30,504,505],{},"{ id }","를 전달하면 runId가 ",[30,508,509],{},"\u003Cflow>:\u003Cid>","로 고정됩니다.",[19,512],{},"\n같은 ID로 두 번째 시작하면 새 Run이 생성되지 않고 기존 runId가 반환됩니다.",[19,515],{},"\n재시도되는 HTTP 핸들러에서 호출해도 Run이 중복되지 않습니다.",[19,518],{},"\n네 번째 인자의 ",[30,521,522],{},"{ deadlineMs }","는 Run 전체의 ",[412,525,527],{"href":526},"#%E6%9C%9F%E9%99%90","기한","입니다.",[23,530,531],{"id":531},"fan-out",[15,533,534,535,538,539,541,544,545,547,548,550,551,191,554,557,558,560,563,564,566,567,569],{},"배열의 요소 수에 따른 병렬 처리는 ",[30,536,537],{},"f.fanOut","으로 정의합니다.",[19,540],{},[30,542,543],{},"over","가 반환한 요소마다 자식 node가 하나씩 생성됩니다.",[19,546],{},"\n자식 node의 ID는 요소의 인덱스입니다.",[19,549],{},"\n예를 들어 ",[30,552,553],{},"greet:0",[30,555,556],{},"greet:1","이 됩니다.",[19,559],{},[30,561,562],{},"key","를 전달한 경우에는 인덱스 대신 ",[30,565,562],{},"의 반환값이 사용됩니다.",[19,568],{},"\n사용할 수 있는 문자는 node ID와 같습니다.",[15,571,572],{},"후속 node가 받는 것은 다음 형식의 집계값입니다.",[42,574,576],{"className":44,"code":575,"language":46,"meta":47,"style":47},"{ total: 3, succeeded: 2, failed: 1 }\n",[30,577,578],{"__ignoreMap":47},[51,579,580,583,586,589,592,594,597,599,602,604,607,609,612],{"class":53,"line":54},[51,581,582],{"class":61},"{ ",[51,584,585],{"class":108},"total",[51,587,588],{"class":61},": ",[51,590,591],{"class":88},"3",[51,593,191],{"class":61},[51,595,596],{"class":108},"succeeded",[51,598,588],{"class":61},[51,600,601],{"class":88},"2",[51,603,191],{"class":61},[51,605,606],{"class":108},"failed",[51,608,588],{"class":61},[51,610,611],{"class":88},"1",[51,613,614],{"class":61}," }\n",[15,616,617,618,620,621,623,624,626,627,629],{},"자식 node별 반환값은 후속 node에 전달되지 않습니다.",[19,619],{},"\n개별 결과가 필요하면 performer가 R2나 D1 등에 기록하고 그 참조를 반환값으로 사용하세요.",[19,622],{},"\n자식 node가 실패해도 fan-out node 자체는 실패하지 않습니다.",[19,625],{},"\n실패 여부는 후속 node가 받는 ",[30,628,606],{}," 값으로 판단합니다.",[23,631,633],{"id":632},"perform内からのノード追加","perform 내부에서 node 추가",[15,635,636,639],{},[30,637,638],{},"ctx.spawn","을 호출하면 실행 중인 node에 자식 node가 추가됩니다.",[42,641,643],{"className":44,"code":642,"language":46,"meta":47,"style":47},"class Crawl extends Performer\u003C{ url: string }, void, {}, Env> {\n  async perform(payload: { url: string }, ctx: JobContext): Promise\u003Cvoid> {\n    for (const found of await this.discover(payload.url)) {\n      ctx.spawn(found.id, 'CRAWL', { url: found.url });\n    }\n  }\n}\n",[30,644,645,683,732,762,779,784,789],{"__ignoreMap":47},[51,646,647,650,653,656,659,661,664,666,668,671,674,677,680],{"class":53,"line":54},[51,648,649],{"class":57},"class",[51,651,652],{"class":108}," Crawl",[51,654,655],{"class":57}," extends",[51,657,658],{"class":108}," Performer",[51,660,141],{"class":61},[51,662,663],{"class":144},"url",[51,665,148],{"class":57},[51,667,151],{"class":88},[51,669,670],{"class":61}," }, ",[51,672,673],{"class":88},"void",[51,675,676],{"class":61},", {}, ",[51,678,679],{"class":108},"Env",[51,681,682],{"class":61},"> {\n",[51,684,685,688,691,693,696,698,701,703,705,707,709,712,714,717,720,722,725,728,730],{"class":53,"line":75},[51,686,687],{"class":57},"  async",[51,689,690],{"class":108}," perform",[51,692,185],{"class":61},[51,694,695],{"class":144},"payload",[51,697,148],{"class":57},[51,699,700],{"class":61}," { ",[51,702,663],{"class":144},[51,704,148],{"class":57},[51,706,151],{"class":88},[51,708,670],{"class":61},[51,710,711],{"class":144},"ctx",[51,713,148],{"class":57},[51,715,716],{"class":108}," JobContext",[51,718,719],{"class":61},")",[51,721,148],{"class":57},[51,723,724],{"class":108}," Promise",[51,726,727],{"class":61},"\u003C",[51,729,673],{"class":88},[51,731,682],{"class":61},[51,733,734,737,740,742,745,748,750,753,756,759],{"class":53,"line":82},[51,735,736],{"class":57},"    for",[51,738,739],{"class":61}," (",[51,741,85],{"class":57},[51,743,744],{"class":88}," found",[51,746,747],{"class":57}," of",[51,749,472],{"class":57},[51,751,752],{"class":88}," this",[51,754,755],{"class":61},".",[51,757,758],{"class":108},"discover",[51,760,761],{"class":61},"(payload.url)) {\n",[51,763,764,767,770,773,776],{"class":53,"line":98},[51,765,766],{"class":61},"      ctx.",[51,768,769],{"class":108},"spawn",[51,771,772],{"class":61},"(found.id, ",[51,774,775],{"class":68},"'CRAWL'",[51,777,778],{"class":61},", { url: found.url });\n",[51,780,781],{"class":53,"line":115},[51,782,783],{"class":61},"    }\n",[51,785,786],{"class":53,"line":120},[51,787,788],{"class":61},"  }\n",[51,790,791],{"class":53,"line":133},[51,792,793],{"class":61},"}\n",[15,795,796,797,799,800,803,804,806,807,809,812,813,815,816,818],{},"첫 번째 인자인 ID는 필수입니다.",[19,798],{},"\n자식 node의 ID는 ",[30,801,802],{},"\u003C부모의 node ID>:\u003C지정한 ID>","로 구성되며, 사용할 수 있는 문자는 node ID와 같습니다.",[19,805],{},"\n같은 ID로 여러 번 호출해도 자식 node는 중복 생성되지 않습니다.",[19,808],{},[30,810,811],{},"perform","이 실패한 시도에서 추가된 자식 node는 생성되지 않습니다.",[19,814],{},"\n재실행 시의 ",[30,817,811],{},"에서 다시 추가하세요.",[15,820,821,823,824,826,827,829,830,837],{},[30,822,769],{},"에는 타입 검사가 적용되지 않습니다.",[19,825],{},"\nbinding 이름과 payload는 실행 시점의 값으로 전달합니다.",[19,828],{},"\n다른 Worker의 performer에서 호출하는 경우에는 ",[412,831,833,836],{"href":832},"\u002Fko\u002Fguide\u002Fperformer#%E5%88%A5worker%E3%81%AB%E9%85%8D%E7%BD%AE%E3%81%97%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E5%88%B6%E7%B4%84",[30,834,835],{},"await","가 필요","합니다.",[23,839,840],{"id":840},"subflow",[15,842,843,846,847,849],{},[30,844,845],{},"f.subflow","는 다른 Flow를 Run으로 시작합니다.",[19,848],{},"\nnode는 해당 Run이 종료된 시점에 완료됩니다.",[42,851,853],{"className":44,"code":852,"language":46,"meta":47,"style":47},"const REPORTING = flow\u003C{ ids: string[] }>((f) => {\n  \u002F\u002F ...\n});\n\nconst PIPELINE = flow\u003C{ prefix: string }>((f) => {\n  const list = f.node('list', 'LIST', { input: (i) => ({ prefix: i.prefix }) });\n  const reported = f.subflow('report', REPORTING, { input: (_i, d) => ({ ids: d.list.ids }) });\n  f.node('notify', 'NOTIFY', { after: { reported }, input: () => ({}) });\n});\n",[30,854,855,886,891,896,900,929,967,1008,1038],{"__ignoreMap":47},[51,856,857,859,862,864,866,868,871,873,875,878,880,882,884],{"class":53,"line":54},[51,858,85],{"class":57},[51,860,861],{"class":88}," REPORTING",[51,863,92],{"class":57},[51,865,103],{"class":108},[51,867,141],{"class":61},[51,869,870],{"class":144},"ids",[51,872,148],{"class":57},[51,874,151],{"class":88},[51,876,877],{"class":61},"[] }>((",[51,879,157],{"class":144},[51,881,160],{"class":61},[51,883,163],{"class":57},[51,885,130],{"class":61},[51,887,888],{"class":53,"line":75},[51,889,890],{"class":397},"  \u002F\u002F ...\n",[51,892,893],{"class":53,"line":82},[51,894,895],{"class":61},"});\n",[51,897,898],{"class":53,"line":98},[51,899,79],{"emptyLinePlaceholder":78},[51,901,902,904,907,909,911,913,915,917,919,921,923,925,927],{"class":53,"line":115},[51,903,85],{"class":57},[51,905,906],{"class":88}," PIPELINE",[51,908,92],{"class":57},[51,910,103],{"class":108},[51,912,141],{"class":61},[51,914,145],{"class":144},[51,916,148],{"class":57},[51,918,151],{"class":88},[51,920,154],{"class":61},[51,922,157],{"class":144},[51,924,160],{"class":61},[51,926,163],{"class":57},[51,928,130],{"class":61},[51,930,931,934,936,938,940,942,944,946,948,951,954,956,958,960,962,964],{"class":53,"line":120},[51,932,933],{"class":57},"  const",[51,935,174],{"class":88},[51,937,92],{"class":57},[51,939,179],{"class":61},[51,941,182],{"class":108},[51,943,185],{"class":61},[51,945,188],{"class":68},[51,947,191],{"class":61},[51,949,950],{"class":68},"'LIST'",[51,952,953],{"class":61},", { ",[51,955,424],{"class":108},[51,957,206],{"class":61},[51,959,209],{"class":144},[51,961,160],{"class":61},[51,963,163],{"class":57},[51,965,966],{"class":61}," ({ prefix: i.prefix }) });\n",[51,968,969,971,974,976,978,980,982,984,986,989,991,993,995,997,999,1001,1003,1005],{"class":53,"line":133},[51,970,933],{"class":57},[51,972,973],{"class":88}," reported",[51,975,92],{"class":57},[51,977,179],{"class":61},[51,979,840],{"class":108},[51,981,185],{"class":61},[51,983,323],{"class":68},[51,985,191],{"class":61},[51,987,988],{"class":88},"REPORTING",[51,990,953],{"class":61},[51,992,424],{"class":108},[51,994,206],{"class":61},[51,996,271],{"class":144},[51,998,191],{"class":61},[51,1000,276],{"class":144},[51,1002,160],{"class":61},[51,1004,163],{"class":57},[51,1006,1007],{"class":61}," ({ ids: d.list.ids }) });\n",[51,1009,1010,1013,1015,1017,1020,1022,1025,1028,1030,1033,1035],{"class":53,"line":168},[51,1011,1012],{"class":61},"  f.",[51,1014,182],{"class":108},[51,1016,185],{"class":61},[51,1018,1019],{"class":68},"'notify'",[51,1021,191],{"class":61},[51,1023,1024],{"class":68},"'NOTIFY'",[51,1026,1027],{"class":61},", { after: { reported }, ",[51,1029,424],{"class":108},[51,1031,1032],{"class":61},": () ",[51,1034,163],{"class":57},[51,1036,1037],{"class":61}," ({}) });\n",[51,1039,1040],{"class":53,"line":200},[51,1041,895],{"class":61},[15,1043,1044,1045,1047,1049,1050,1052,1053,1056,1057,1059],{},"두 번째 인자에는 Flow 정의 자체를 전달합니다.",[19,1046],{},[30,1048,424],{},"의 타입은 전달한 Flow의 타입 인자에서 도출됩니다.",[19,1051],{},"\n시작할 Flow는 ",[30,1054,1055],{},"flows","에 등록해야 합니다.",[19,1058],{},"\n등록하지 않은 경우 시작 시 오류가 발생합니다.",[15,1061,1062,1063,528,1066,1068,1069,1071,1072,191,1075,191,1078,1081,1082,1084],{},"자식 Run의 runId는 ",[30,1064,1065],{},"\u003C자식 Flow 이름>:\u003C부모 runId의 로컬 부분>-\u003Cnode ID>",[19,1067],{},"\n자식 Run의 상태가 그대로 node의 상태로 반영됩니다.",[19,1070],{},"\n상태는 ",[30,1073,1074],{},"COMPLETED",[30,1076,1077],{},"FAILED",[30,1079,1080],{},"CANCELLED"," 중 하나입니다.",[19,1083],{},"\n부모 Run을 취소하면 자식 Run도 취소됩니다.",[15,1086,1087,1088,1090,1091,1093,1094,1098],{},"부모 node는 자식 Run의 반환값을 받지 않습니다.",[19,1089],{},"\n결과가 필요하면 performer가 R2나 D1 등에 기록하세요.",[19,1092],{},"\n중첩 상한은 ",[412,1095,1097],{"href":1096},"#%E5%88%B6%E7%B4%84","제약","을 참조하세요.",[23,1100,1102],{"id":1101},"待ち合わせ","대기 합류",[15,1104,1105,1106,1108,1110,1111,1113],{},"node는 자신과 자손 node가 모두 종료된 시점에 완료됩니다.",[19,1107],{},[30,1109,431],{},"로 지정한 node에 의존하는 후속 node는 fan-out의 자식 node와 ",[30,1112,769],{},"으로 추가된 자손 node가 종료된 후에 실행됩니다.",[23,1115,1117],{"id":1116},"実行条件","실행 조건",[15,1119,1120,1121,1123,1126],{},"기본적으로 의존하는 node가 모두 성공했을 때만 node가 실행됩니다.",[19,1122],{},[30,1124,1125],{},"trigger","는 의존하는 node가 실패한 경우의 동작을 지정합니다.",[1128,1129,1130,1143],"table",{},[1131,1132,1133],"thead",{},[1134,1135,1136,1140],"tr",{},[1137,1138,1139],"th",{},"값",[1137,1141,1142],{},"실행되는 조건",[1144,1145,1146,1157,1175],"tbody",{},[1134,1147,1148,1154],{},[1149,1150,1151],"td",{},[30,1152,1153],{},"'success'",[1149,1155,1156],{},"의존하는 node가 모두 성공. 기본값",[1134,1158,1159,1164],{},[1149,1160,1161],{},[30,1162,1163],{},"'failure'",[1149,1165,1166,1167,191,1169,191,1172,1174],{},"의존하는 node 중 하나 이상이 ",[30,1168,1077],{},[30,1170,1171],{},"STALLED",[30,1173,1080],{}," 중 하나",[1134,1176,1177,1182],{},[1149,1178,1179],{},[30,1180,1181],{},"'always'",[1149,1183,1184],{},"의존하는 node가 모두 종료. 성공 여부는 불문",[42,1186,1188],{"className":44,"code":1187,"language":46,"meta":47,"style":47},"const flows = {\n  BACKUP: flow\u003C{ target: string }>((f) => {\n    const dump = f.node('dump', 'DUMP', { input: (i) => ({ target: i.target }) });\n\n    \u002F\u002F 실패했을 때만 실행\n    f.node('alert', 'ALERT', {\n      after: { dump },\n      trigger: 'failure',\n      input: (i) => ({ message: `backup failed: ${i.target}` }),\n    });\n\n    \u002F\u002F 성공 여부와 무관하게 실행\n    f.node('unlock', 'UNLOCK', { after: { dump }, trigger: 'always', input: (i) => ({ target: i.target }) });\n  }),\n};\n",[30,1189,1190,1200,1226,1264,1268,1273,1291,1296,1306,1336,1340,1344,1349,1384,1388],{"__ignoreMap":47},[51,1191,1192,1194,1196,1198],{"class":53,"line":54},[51,1193,85],{"class":57},[51,1195,125],{"class":88},[51,1197,92],{"class":57},[51,1199,130],{"class":61},[51,1201,1202,1205,1207,1209,1212,1214,1216,1218,1220,1222,1224],{"class":53,"line":75},[51,1203,1204],{"class":61},"  BACKUP: ",[51,1206,13],{"class":108},[51,1208,141],{"class":61},[51,1210,1211],{"class":144},"target",[51,1213,148],{"class":57},[51,1215,151],{"class":88},[51,1217,154],{"class":61},[51,1219,157],{"class":144},[51,1221,160],{"class":61},[51,1223,163],{"class":57},[51,1225,130],{"class":61},[51,1227,1228,1230,1233,1235,1237,1239,1241,1244,1246,1249,1251,1253,1255,1257,1259,1261],{"class":53,"line":82},[51,1229,171],{"class":57},[51,1231,1232],{"class":88}," dump",[51,1234,92],{"class":57},[51,1236,179],{"class":61},[51,1238,182],{"class":108},[51,1240,185],{"class":61},[51,1242,1243],{"class":68},"'dump'",[51,1245,191],{"class":61},[51,1247,1248],{"class":68},"'DUMP'",[51,1250,953],{"class":61},[51,1252,424],{"class":108},[51,1254,206],{"class":61},[51,1256,209],{"class":144},[51,1258,160],{"class":61},[51,1260,163],{"class":57},[51,1262,1263],{"class":61}," ({ target: i.target }) });\n",[51,1265,1266],{"class":53,"line":98},[51,1267,79],{"emptyLinePlaceholder":78},[51,1269,1270],{"class":53,"line":115},[51,1271,1272],{"class":397},"    \u002F\u002F 실패했을 때만 실행\n",[51,1274,1275,1277,1279,1281,1284,1286,1289],{"class":53,"line":120},[51,1276,316],{"class":61},[51,1278,182],{"class":108},[51,1280,185],{"class":61},[51,1282,1283],{"class":68},"'alert'",[51,1285,191],{"class":61},[51,1287,1288],{"class":68},"'ALERT'",[51,1290,197],{"class":61},[51,1292,1293],{"class":53,"line":133},[51,1294,1295],{"class":61},"      after: { dump },\n",[51,1297,1298,1301,1303],{"class":53,"line":168},[51,1299,1300],{"class":61},"      trigger: ",[51,1302,1163],{"class":68},[51,1304,1305],{"class":61},",\n",[51,1307,1308,1310,1312,1314,1316,1318,1321,1324,1326,1328,1330,1333],{"class":53,"line":200},[51,1309,203],{"class":108},[51,1311,206],{"class":61},[51,1313,209],{"class":144},[51,1315,160],{"class":61},[51,1317,163],{"class":57},[51,1319,1320],{"class":61}," ({ message: ",[51,1322,1323],{"class":68},"`backup failed: ${",[51,1325,209],{"class":61},[51,1327,755],{"class":68},[51,1329,1211],{"class":61},[51,1331,1332],{"class":68},"}`",[51,1334,1335],{"class":61}," }),\n",[51,1337,1338],{"class":53,"line":219},[51,1339,222],{"class":61},[51,1341,1342],{"class":53,"line":225},[51,1343,79],{"emptyLinePlaceholder":78},[51,1345,1346],{"class":53,"line":230},[51,1347,1348],{"class":397},"    \u002F\u002F 성공 여부와 무관하게 실행\n",[51,1350,1351,1353,1355,1357,1360,1362,1365,1368,1370,1372,1374,1376,1378,1380,1382],{"class":53,"line":257},[51,1352,316],{"class":61},[51,1354,182],{"class":108},[51,1356,185],{"class":61},[51,1358,1359],{"class":68},"'unlock'",[51,1361,191],{"class":61},[51,1363,1364],{"class":68},"'UNLOCK'",[51,1366,1367],{"class":61},", { after: { dump }, trigger: ",[51,1369,1181],{"class":68},[51,1371,191],{"class":61},[51,1373,424],{"class":108},[51,1375,206],{"class":61},[51,1377,209],{"class":144},[51,1379,160],{"class":61},[51,1381,163],{"class":57},[51,1383,1263],{"class":61},[51,1385,1386],{"class":53,"line":263},[51,1387,367],{"class":61},[51,1389,1390],{"class":53,"line":286},[51,1391,373],{"class":61},[15,1393,1394,1396,1397,1399,1400,1402,1404,1405,1407,1409,1410,1413,1414,1417,1418,1420,1421,1423,1424,1426],{},[30,1395,431],{},"가 없는 node에 ",[30,1398,1125],{},"를 지정하면 오류가 발생합니다.",[19,1401],{},[30,1403,1163],{}," 조건에서 실패로 집계하는 것은 실제로 실패한 node뿐입니다.",[19,1406],{},[30,1408,1125],{},"나 ",[30,1411,1412],{},"when"," 조건을 만족하지 못해 ",[30,1415,1416],{},"SKIPPED","가 된 node는 실패로 집계하지 않습니다.",[19,1419],{},"\n의존하는 node가 모두 ",[30,1422,1416],{},"이면 ",[30,1425,1163],{}," node는 실행되지 않습니다.",[15,1428,1429,1431,1432,1434,1435,1437,1439,1440,1443],{},[30,1430,1163],{},"와 ",[30,1433,1181],{},"에서는 실패한 node의 반환값이 없습니다.",[19,1436],{},[30,1438,424],{},"의 두 번째 인자 타입에는 ",[30,1441,1442],{},"undefined","가 포함되므로 값이 없는 경우의 처리를 작성하세요.",[42,1445,1447],{"className":44,"code":1446,"language":46,"meta":47,"style":47},"f.node('alert', 'ALERT', {\n  after: { dump },\n  trigger: 'always',\n  \u002F\u002F d.dump는 undefined일 수 있음\n  input: (_i, d) => ({ size: d.dump?.size ?? 0 }),\n});\n",[30,1448,1449,1466,1471,1480,1485,1513],{"__ignoreMap":47},[51,1450,1451,1454,1456,1458,1460,1462,1464],{"class":53,"line":54},[51,1452,1453],{"class":61},"f.",[51,1455,182],{"class":108},[51,1457,185],{"class":61},[51,1459,1283],{"class":68},[51,1461,191],{"class":61},[51,1463,1288],{"class":68},[51,1465,197],{"class":61},[51,1467,1468],{"class":53,"line":75},[51,1469,1470],{"class":61},"  after: { dump },\n",[51,1472,1473,1476,1478],{"class":53,"line":82},[51,1474,1475],{"class":61},"  trigger: ",[51,1477,1181],{"class":68},[51,1479,1305],{"class":61},[51,1481,1482],{"class":53,"line":98},[51,1483,1484],{"class":397},"  \u002F\u002F d.dump는 undefined일 수 있음\n",[51,1486,1487,1490,1492,1494,1496,1498,1500,1502,1505,1508,1511],{"class":53,"line":115},[51,1488,1489],{"class":108},"  input",[51,1491,206],{"class":61},[51,1493,271],{"class":144},[51,1495,191],{"class":61},[51,1497,276],{"class":144},[51,1499,160],{"class":61},[51,1501,163],{"class":57},[51,1503,1504],{"class":61}," ({ size: d.dump?.size ",[51,1506,1507],{"class":57},"??",[51,1509,1510],{"class":88}," 0",[51,1512,1335],{"class":61},[51,1514,1515],{"class":53,"line":120},[51,1516,895],{"class":61},[23,1518,1520],{"id":1519},"条件分岐","조건 분기",[15,1522,1523,1525,1526,1528,1530,1531,1534,1535,1537,1538,1540,1542,1543,1545],{},[30,1524,1412],{},"은 Flow의 입력이나 앞 단계의 결과를 바탕으로 node의 실행 여부를 결정합니다.",[19,1527],{},[30,1529,1412],{},"이 ",[30,1532,1533],{},"false","를 반환하면 해당 node는 ",[30,1536,1416],{},"로 전이되고, 의존하는 후속 node도 실행되지 않습니다.",[19,1539],{},[30,1541,1412],{}," 내부에서 예외가 발생하면 node는 ",[30,1544,1077],{},"로 전이됩니다.",[42,1547,1549],{"className":44,"code":1548,"language":46,"meta":47,"style":47},"f.node('detail', 'DETAIL', {\n  after: { list },\n  when: (i, d) => i.verbose && d.list.items.length > 0,\n  input: (_i, d) => ({ items: d.list.items }),\n});\n",[30,1550,1551,1569,1574,1610,1629],{"__ignoreMap":47},[51,1552,1553,1555,1557,1559,1562,1564,1567],{"class":53,"line":54},[51,1554,1453],{"class":61},[51,1556,182],{"class":108},[51,1558,185],{"class":61},[51,1560,1561],{"class":68},"'detail'",[51,1563,191],{"class":61},[51,1565,1566],{"class":68},"'DETAIL'",[51,1568,197],{"class":61},[51,1570,1571],{"class":53,"line":75},[51,1572,1573],{"class":61},"  after: { list },\n",[51,1575,1576,1579,1581,1583,1585,1587,1589,1591,1594,1597,1600,1603,1606,1608],{"class":53,"line":82},[51,1577,1578],{"class":108},"  when",[51,1580,206],{"class":61},[51,1582,209],{"class":144},[51,1584,191],{"class":61},[51,1586,276],{"class":144},[51,1588,160],{"class":61},[51,1590,163],{"class":57},[51,1592,1593],{"class":61}," i.verbose ",[51,1595,1596],{"class":57},"&&",[51,1598,1599],{"class":61}," d.list.items.",[51,1601,1602],{"class":88},"length",[51,1604,1605],{"class":57}," >",[51,1607,1510],{"class":88},[51,1609,1305],{"class":61},[51,1611,1612,1614,1616,1618,1620,1622,1624,1626],{"class":53,"line":98},[51,1613,1489],{"class":108},[51,1615,206],{"class":61},[51,1617,271],{"class":144},[51,1619,191],{"class":61},[51,1621,276],{"class":144},[51,1623,160],{"class":61},[51,1625,163],{"class":57},[51,1627,1628],{"class":61}," ({ items: d.list.items }),\n",[51,1630,1631],{"class":53,"line":115},[51,1632,895],{"class":61},[15,1634,1635,1637,1638,1640],{},[30,1636,1412],{},"과 ",[30,1639,424],{},"을 평가할 때는 인자의 값만 사용하고 외부에 대한 조회는 하지 마세요.",[23,1642,1644],{"id":1643},"失敗時の動作","실패 시 동작",[15,1646,1647,1648,1650,1651,1545,1653,1655,1657,1658,1660,1661,1663,1664,1666,1667,1669,1670,1545],{},"node가 실패하면 ",[30,1649,1153],{},"로 의존하는 후속 node는 ",[30,1652,1416],{},[19,1654],{},[30,1656,1125],{},"가 ",[30,1659,1163],{}," 또는 ",[30,1662,1181],{},"인 후속 node는 실행됩니다.",[19,1665],{},"\n실패한 node에 의존하지 않는 node는 끝까지 실행됩니다.",[19,1668],{},"\n모든 node가 종료되면 Run은 ",[30,1671,1077],{},[15,1673,1674,1675,1677,1678,1680,1409,1682,1684,1685,1687,1690,1691,1693,1694,1696,1698,1699,1702],{},"Run이 ",[30,1676,1077],{},"가 되는 것은 실패한 node가 있는 경우뿐입니다.",[19,1679],{},[30,1681,1125],{},[30,1683,1412],{}," 조건 때문에 실행되지 않은 node는 실패로 집계하지 않습니다.",[19,1686],{},[30,1688,1689],{},"trigger: 'failure'"," node가 성공하더라도 앞 단계 node가 실패했다면 Run은 ",[30,1692,1077],{},"로 종료됩니다.",[19,1695],{},[30,1697,1416],{},"가 된 이유는 node의 ",[30,1700,1701],{},"error","에 기록되며 대시보드의 Run 상세 화면에 표시됩니다.",[15,1704,1705,1707,1708,1710],{},[30,1706,1077],{}," 상태의 Run은 대시보드 또는 REST API로 재개합니다.",[19,1709],{},"\n성공한 node의 결과는 그대로 사용되고, 그 외의 node는 미실행 상태로 간주되어 다시 실행됩니다.",[23,1712,1714],{"id":1713},"取り消し","취소",[15,1716,1717,1718,1720,1721,1725,1726,1728,1729,1731,1732,1735,1736,1545],{},"Run을 취소하면 미실행 node는 시작되지 않습니다.",[19,1719],{},"\n실행 중인 node에는 ",[412,1722,1724],{"href":1723},"\u002Fko\u002Fguide\u002Fexecution#%E5%AE%9F%E8%A1%8C%E4%B8%AD%E3%81%AE%E5%8F%96%E3%82%8A%E6%B6%88%E3%81%97","취소 요청","이 전송됩니다.",[19,1727],{},"\n실행 중인 작업은 중지되지 않습니다.",[19,1730],{},"\nperformer가 요청을 확인하고 종료하거나, 요청 후 ",[30,1733,1734],{},"reaperGraceMs","(기본 30초)가 지나도 결과가 보고되지 않으면 Run은 ",[30,1737,1080],{},[23,1739,527],{"id":1740},"期限",[15,1742,1743],{},"Run 전체의 기한은 Flow 정의의 두 번째 인자로 지정합니다.",[42,1745,1747],{"className":44,"code":1746,"language":46,"meta":47,"style":47},"const GREETINGS = flow\u003C{ prefix: string }>(\n  (f) => {\n    \u002F\u002F ...\n  },\n  { deadlineMs: 10 * 60 * 1000 },\n);\n",[30,1748,1749,1771,1784,1789,1794,1816],{"__ignoreMap":47},[51,1750,1751,1753,1756,1758,1760,1762,1764,1766,1768],{"class":53,"line":54},[51,1752,85],{"class":57},[51,1754,1755],{"class":88}," GREETINGS",[51,1757,92],{"class":57},[51,1759,103],{"class":108},[51,1761,141],{"class":61},[51,1763,145],{"class":144},[51,1765,148],{"class":57},[51,1767,151],{"class":88},[51,1769,1770],{"class":61}," }>(\n",[51,1772,1773,1776,1778,1780,1782],{"class":53,"line":75},[51,1774,1775],{"class":61},"  (",[51,1777,157],{"class":144},[51,1779,160],{"class":61},[51,1781,163],{"class":57},[51,1783,130],{"class":61},[51,1785,1786],{"class":53,"line":82},[51,1787,1788],{"class":397},"    \u002F\u002F ...\n",[51,1790,1791],{"class":53,"line":98},[51,1792,1793],{"class":61},"  },\n",[51,1795,1796,1799,1802,1805,1808,1810,1813],{"class":53,"line":115},[51,1797,1798],{"class":61},"  { deadlineMs: ",[51,1800,1801],{"class":88},"10",[51,1803,1804],{"class":57}," *",[51,1806,1807],{"class":88}," 60",[51,1809,1804],{"class":57},[51,1811,1812],{"class":88}," 1000",[51,1814,1815],{"class":61}," },\n",[51,1817,1818],{"class":53,"line":120},[51,1819,1820],{"class":61},");\n",[15,1822,1823,1826,1827,1829,502,1831,1833],{},[30,1824,1825],{},"deadlineMs","는 양의 정수(밀리초)로 지정합니다.",[19,1828],{},[30,1830,478],{},[30,1832,522],{},"를 전달한 경우에는 그 값이 우선합니다.",[15,1835,1836,1837,1839,1840,1843,1844,1545,1846,1848,1849,1545,1851,1853],{},"기한이 지난 Run은 취소와 같은 절차로 중단됩니다.",[19,1838],{},"\n미실행 node는 ",[30,1841,1842],{},"run deadline exceeded"," 오류와 함께 ",[30,1845,1077],{},[19,1847],{},"\n실행 중인 작업은 중지되지 않으며, 해당 작업이 종료된 시점에 Run이 ",[30,1850,1077],{},[19,1852],{},"\n실행 중인 자식 Run은 취소됩니다.",[15,1855,1856,1857,1545,1859,1861,1862,1864],{},"기한까지 종료되지 않은 Run은 나머지 node가 모두 성공하더라도 ",[30,1858,1077],{},[19,1860],{},"\n이 Run은 일반적인 실패와 마찬가지로 재개 대상입니다.",[19,1863],{},"\n재개하면 기한은 재개한 시점부터 다시 계측됩니다.",[23,1866,1868],{"id":1867},"保持期間","보존 기간",[15,1870,1871,1872,1875,1876,1878,1880,1881,1884,1885,1887,1888,1892],{},"종료된 Run은 ",[30,1873,1874],{},"runs.sweepAfterMs","(기본 5분)가 경과한 후 삭제됩니다.",[19,1877],{},[30,1879,1077],{}," 상태의 Run은 ",[30,1882,1883],{},"runs.failedRetentionMs","(기본 7일)가 경과한 후 삭제됩니다.",[19,1886],{},"\n자세한 내용은 ",[412,1889,1891],{"href":1890},"\u002Fko\u002Freference\u002Fconfig#runsettings","RunSettings","를 참조하세요.",[23,1894,1896],{"id":1895},"デプロイと実行中のrun","배포와 실행 중인 Run",[15,1898,1899,1900,1902,1904],{},"실행 중인 Run은 시작 시점의 node 구성으로 계속됩니다.",[19,1901],{},[30,1903,424],{}," 등의 함수를 변경해도 다음에 시작되는 node부터 반영됩니다.",[15,1906,1907,1908,1910],{},"정의에서 node를 삭제하면 그 node를 포함하는 실행 중인 Run은 해당 node에서 실패합니다.",[19,1909],{},"\nnode를 삭제할 때는 실행 중인 모든 Run이 종료된 후에 배포하세요.",[23,1912,1914],{"id":1913},"テスト","테스트",[15,1916,1917,1920,1921,1923],{},[30,1918,1919],{},"simulateFlow","는 지정한 입력에 대한 node의 실행 순서와 각 node에 전달되는 payload를 검증합니다.",[19,1922],{},"\nperformer의 실제 처리는 실행되지 않습니다.",[42,1925,1927],{"className":44,"code":1926,"language":46,"meta":47,"style":47},"import { simulateFlow } from 'tsumugi\u002Ftesting';\n\nconst result = simulateFlow(flows.GREETINGS, { prefix: 'hello' }, { results: { list: { names: ['a', 'b'] } } });\n\nexpect(result.nodes.map((node) => node.id)).toEqual(['list', 'greet:0', 'greet:1', 'greet', 'report']);\nexpect(result.nodes[1].payload).toEqual({ name: 'a' });\n",[30,1928,1929,1943,1947,1983,1987,2039],{"__ignoreMap":47},[51,1930,1931,1933,1936,1938,1941],{"class":53,"line":54},[51,1932,58],{"class":57},[51,1934,1935],{"class":61}," { simulateFlow } ",[51,1937,65],{"class":57},[51,1939,1940],{"class":68}," 'tsumugi\u002Ftesting'",[51,1942,72],{"class":61},[51,1944,1945],{"class":53,"line":75},[51,1946,79],{"emptyLinePlaceholder":78},[51,1948,1949,1951,1954,1956,1959,1962,1965,1967,1969,1972,1975,1977,1980],{"class":53,"line":82},[51,1950,85],{"class":57},[51,1952,1953],{"class":88}," result",[51,1955,92],{"class":57},[51,1957,1958],{"class":108}," simulateFlow",[51,1960,1961],{"class":61},"(flows.",[51,1963,1964],{"class":88},"GREETINGS",[51,1966,487],{"class":61},[51,1968,490],{"class":68},[51,1970,1971],{"class":61}," }, { results: { list: { names: [",[51,1973,1974],{"class":68},"'a'",[51,1976,191],{"class":61},[51,1978,1979],{"class":68},"'b'",[51,1981,1982],{"class":61},"] } } });\n",[51,1984,1985],{"class":53,"line":98},[51,1986,79],{"emptyLinePlaceholder":78},[51,1988,1989,1992,1995,1998,2001,2003,2005,2007,2010,2013,2016,2018,2020,2023,2025,2028,2030,2032,2034,2036],{"class":53,"line":115},[51,1990,1991],{"class":108},"expect",[51,1993,1994],{"class":61},"(result.nodes.",[51,1996,1997],{"class":108},"map",[51,1999,2000],{"class":61},"((",[51,2002,182],{"class":144},[51,2004,160],{"class":61},[51,2006,163],{"class":57},[51,2008,2009],{"class":61}," node.id)).",[51,2011,2012],{"class":108},"toEqual",[51,2014,2015],{"class":61},"([",[51,2017,188],{"class":68},[51,2019,191],{"class":61},[51,2021,2022],{"class":68},"'greet:0'",[51,2024,191],{"class":61},[51,2026,2027],{"class":68},"'greet:1'",[51,2029,191],{"class":61},[51,2031,247],{"class":68},[51,2033,191],{"class":61},[51,2035,323],{"class":68},[51,2037,2038],{"class":61},"]);\n",[51,2040,2041,2043,2046,2048,2051,2053,2056,2058],{"class":53,"line":120},[51,2042,1991],{"class":108},[51,2044,2045],{"class":61},"(result.nodes[",[51,2047,611],{"class":88},[51,2049,2050],{"class":61},"].payload).",[51,2052,2012],{"class":108},[51,2054,2055],{"class":61},"({ name: ",[51,2057,1974],{"class":68},[51,2059,401],{"class":61},[15,2061,2062,2063,2066,2067,2069,2070,2072,2073,528,2075,2077,2080,2081,1545,2083,2085,2086,1545,2088,2090,2091,2093,2094,2096],{},"각 node의 반환값은 ",[30,2064,2065],{},"results","에 node ID를 키로 하여 전달합니다.",[19,2068],{},"\n값으로는 반환값 자체와 반환값을 만드는 함수를 모두 받을 수 있습니다.",[19,2071],{},"\n전달하지 않은 node의 반환값은 ",[30,2074,1442],{},[19,2076],{},[30,2078,2079],{},"fails","에 전달한 node는 실패하며 후속 node는 ",[30,2082,1416],{},[19,2084],{},"\nRun은 ",[30,2087,1077],{},[19,2089],{},"\nfan-out의 자식 node는 ",[30,2092,543],{},"의 반환값에서 생성되지만, ",[30,2095,638],{},"으로 추가되는 자식 node는 포함되지 않습니다.",[23,2098,1097],{"id":2099},"制約",[15,2101,2102,2103,2106,2107,2109,2111],{},"node에서는 ",[30,2104,2105],{},"uniqueKey","를 사용할 수 없습니다.",[19,2108],{},[30,2110,2105],{},"를 필수로 한 performer를 node에 지정하면 타입 오류가 발생합니다.",[15,2113,2114,2115,2117,2118,2120,2121,2123],{},"node의 반환값이 8,192자를 넘거나 직렬화할 수 없는 경우 해당 시도는 실패로 처리됩니다.",[19,2116],{},"\n실패 후에는 ",[30,2119,438],{},"까지 재시도가 이루어집니다.",[19,2122],{},"\n큰 결과는 R2 등에 기록하고 그 참조를 반환값으로 사용하세요.",[15,2125,2126,2127,2129,2130,2132,2133,2136,2137,1431,2140,2143],{},"하나의 Run에 포함할 수 있는 node 수는 기본적으로 10,000개입니다.",[19,2128],{},"\nsubflow의 중첩은 기본적으로 3단계입니다.",[19,2131],{},"\n상한은 ",[30,2134,2135],{},"defineTsumugi","의 ",[30,2138,2139],{},"runs.maxNodes",[30,2141,2142],{},"runs.maxDepth","로 변경합니다.",[23,2145,2147],{"id":2146},"設定","설정",[15,2149,2150,2152,2153,2155],{},[30,2151,1055],{},"를 지정하는 경우 wrangler 설정에 다음 두 곳을 추가하세요.",[19,2154],{},"\n지정하지 않는 경우에는 이 설정이 필요하지 않습니다.",[42,2157,2161],{"className":2158,"code":2159,"language":2160,"meta":47,"style":47},"language-jsonc shiki shiki-themes github-light github-dark","{\n  \"durable_objects\": {\n    \"bindings\": [\n      { \"name\": \"JOB_SHARD\", \"class_name\": \"TsumugiJobShard\" },\n      { \"name\": \"RUN\", \"class_name\": \"TsumugiRun\" },\n    ],\n  },\n  \"migrations\": [\n    { \"tag\": \"v1\", \"new_sqlite_classes\": [\"TsumugiJobShard\"] },\n    { \"tag\": \"v2\", \"new_sqlite_classes\": [\"TsumugiRun\"] },\n  ],\n}\n","jsonc",[30,2162,2163,2168,2176,2184,2209,2231,2236,2240,2247,2273,2294,2299],{"__ignoreMap":47},[51,2164,2165],{"class":53,"line":54},[51,2166,2167],{"class":61},"{\n",[51,2169,2170,2173],{"class":53,"line":75},[51,2171,2172],{"class":88},"  \"durable_objects\"",[51,2174,2175],{"class":61},": {\n",[51,2177,2178,2181],{"class":53,"line":82},[51,2179,2180],{"class":88},"    \"bindings\"",[51,2182,2183],{"class":61},": [\n",[51,2185,2186,2189,2192,2194,2197,2199,2202,2204,2207],{"class":53,"line":98},[51,2187,2188],{"class":61},"      { ",[51,2190,2191],{"class":88},"\"name\"",[51,2193,588],{"class":61},[51,2195,2196],{"class":68},"\"JOB_SHARD\"",[51,2198,191],{"class":61},[51,2200,2201],{"class":88},"\"class_name\"",[51,2203,588],{"class":61},[51,2205,2206],{"class":68},"\"TsumugiJobShard\"",[51,2208,1815],{"class":61},[51,2210,2211,2213,2215,2217,2220,2222,2224,2226,2229],{"class":53,"line":115},[51,2212,2188],{"class":61},[51,2214,2191],{"class":88},[51,2216,588],{"class":61},[51,2218,2219],{"class":68},"\"RUN\"",[51,2221,191],{"class":61},[51,2223,2201],{"class":88},[51,2225,588],{"class":61},[51,2227,2228],{"class":68},"\"TsumugiRun\"",[51,2230,1815],{"class":61},[51,2232,2233],{"class":53,"line":120},[51,2234,2235],{"class":61},"    ],\n",[51,2237,2238],{"class":53,"line":133},[51,2239,1793],{"class":61},[51,2241,2242,2245],{"class":53,"line":168},[51,2243,2244],{"class":88},"  \"migrations\"",[51,2246,2183],{"class":61},[51,2248,2249,2252,2255,2257,2260,2262,2265,2268,2270],{"class":53,"line":200},[51,2250,2251],{"class":61},"    { ",[51,2253,2254],{"class":88},"\"tag\"",[51,2256,588],{"class":61},[51,2258,2259],{"class":68},"\"v1\"",[51,2261,191],{"class":61},[51,2263,2264],{"class":88},"\"new_sqlite_classes\"",[51,2266,2267],{"class":61},": [",[51,2269,2206],{"class":68},[51,2271,2272],{"class":61},"] },\n",[51,2274,2275,2277,2279,2281,2284,2286,2288,2290,2292],{"class":53,"line":219},[51,2276,2251],{"class":61},[51,2278,2254],{"class":88},[51,2280,588],{"class":61},[51,2282,2283],{"class":68},"\"v2\"",[51,2285,191],{"class":61},[51,2287,2264],{"class":88},[51,2289,2267],{"class":61},[51,2291,2228],{"class":68},[51,2293,2272],{"class":61},[51,2295,2296],{"class":53,"line":225},[51,2297,2298],{"class":61},"  ],\n",[51,2300,2301],{"class":53,"line":230},[51,2302,793],{"class":61},[15,2304,2305,2308,2309,2311,2312,2315,2316,2318],{},[30,2306,2307],{},"TsumugiRun","은 ",[30,2310,2135],{},"의 반환값에 포함된 ",[30,2313,2314],{},"runClass","를 상속하여 export하세요.",[19,2317],{},"\nD1 마이그레이션은 다시 적용해야 합니다.",[42,2320,2322],{"className":44,"code":2321,"language":46,"meta":47,"style":47},"export { TsumugiJobShard } from 'tsumugi';\nexport class TsumugiRun extends tsumugi.runClass {}\n",[30,2323,2324,2338],{"__ignoreMap":47},[51,2325,2326,2329,2332,2334,2336],{"class":53,"line":54},[51,2327,2328],{"class":57},"export",[51,2330,2331],{"class":61}," { TsumugiJobShard } ",[51,2333,65],{"class":57},[51,2335,69],{"class":68},[51,2337,72],{"class":61},[51,2339,2340,2342,2345,2348,2350,2352,2354,2356],{"class":53,"line":75},[51,2341,2328],{"class":57},[51,2343,2344],{"class":57}," class",[51,2346,2347],{"class":108}," TsumugiRun",[51,2349,655],{"class":57},[51,2351,386],{"class":108},[51,2353,755],{"class":61},[51,2355,2314],{"class":108},[51,2357,2358],{"class":61}," {}\n",[42,2360,2364],{"className":2361,"code":2362,"language":2363,"meta":47,"style":47},"language-bash shiki shiki-themes github-light github-dark","pnpm wrangler d1 migrations apply my-jobs --remote\n","bash",[30,2365,2366],{"__ignoreMap":47},[51,2367,2368,2371,2374,2377,2380,2383,2386],{"class":53,"line":54},[51,2369,2370],{"class":108},"pnpm",[51,2372,2373],{"class":68}," wrangler",[51,2375,2376],{"class":68}," d1",[51,2378,2379],{"class":68}," migrations",[51,2381,2382],{"class":68}," apply",[51,2384,2385],{"class":68}," my-jobs",[51,2387,2388],{"class":88}," --remote\n",[2390,2391,2392],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":47,"searchDepth":82,"depth":82,"links":2394},[2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410],{"id":25,"depth":75,"text":26},{"id":454,"depth":75,"text":455},{"id":531,"depth":75,"text":531},{"id":632,"depth":75,"text":633},{"id":840,"depth":75,"text":840},{"id":1101,"depth":75,"text":1102},{"id":1116,"depth":75,"text":1117},{"id":1519,"depth":75,"text":1520},{"id":1643,"depth":75,"text":1644},{"id":1713,"depth":75,"text":1714},{"id":1740,"depth":75,"text":527},{"id":1867,"depth":75,"text":1868},{"id":1895,"depth":75,"text":1896},{"id":1913,"depth":75,"text":1914},{"id":2099,"depth":75,"text":1097},{"id":2146,"depth":75,"text":2147},"의존 관계를 가진 여러 작업을 유향 비순환 그래프(DAG)로 정의하는 Flow의 정의, fan-out, 조건 분기, 실패 시 동작에 대해 설명합니다","md",{},"\u002Fko\u002Fguide\u002Fflow","2026-07-22",{"title":6,"description":2411},"ko\u002Fguide\u002Fflow","2026-10-25","VKyal_NKRT2dGGMIgmnFwXpNjfCMWYYqNwIA6zlJ7T4",false,1794027574004]