|
3 | 3 | createChannelInboundDebouncer, |
4 | 4 | shouldDebounceTextInbound, |
5 | 5 | } from "openclaw/plugin-sdk/channel-inbound"; |
| 6 | +import { fanInChannelIngressLifecycles } from "openclaw/plugin-sdk/channel-ingress-runtime"; |
6 | 7 | import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime"; |
7 | 8 | import { danger } from "openclaw/plugin-sdk/runtime-env"; |
8 | 9 | import { resolveOpenProviderRuntimeGroupPolicy } from "openclaw/plugin-sdk/runtime-group-policy"; |
@@ -58,82 +59,10 @@ type DiscordMessageDispatcherWithLifecycle = DiscordMessageDispatcher & { |
58 | 59 | deactivate: () => Promise<void>; |
59 | 60 | }; |
60 | 61 |
|
61 | | -type DiscordFlushIngressSettlement = { |
62 | | - lifecycle: DiscordIngressLifecycle | undefined; |
63 | | - settle: () => Promise<void>; |
64 | | - abandon: (error?: unknown) => Promise<void>; |
65 | | -}; |
66 | | - |
67 | 62 | function isNonEmptyString(value: string | undefined): value is string { |
68 | 63 | return typeof value === "string" && value.length > 0; |
69 | 64 | } |
70 | 65 |
|
71 | | -function buildFlushIngressLifecycle( |
72 | | - entries: Array<{ turnAdoptionLifecycle?: DiscordIngressLifecycle }>, |
73 | | -): DiscordFlushIngressSettlement { |
74 | | - const lifecycles = entries |
75 | | - .map((entry) => entry.turnAdoptionLifecycle) |
76 | | - .filter((lifecycle) => lifecycle !== undefined); |
77 | | - const [firstLifecycle] = lifecycles; |
78 | | - if (!firstLifecycle) { |
79 | | - return { |
80 | | - lifecycle: undefined, |
81 | | - settle: async () => {}, |
82 | | - abandon: async () => {}, |
83 | | - }; |
84 | | - } |
85 | | - let handedOff = false; |
86 | | - const adoptAll = async () => { |
87 | | - for (const lifecycle of lifecycles) { |
88 | | - await lifecycle.onAdopted(); |
89 | | - } |
90 | | - }; |
91 | | - return { |
92 | | - lifecycle: { |
93 | | - abortSignal: |
94 | | - lifecycles.length === 1 |
95 | | - ? firstLifecycle.abortSignal |
96 | | - : AbortSignal.any(lifecycles.map((lifecycle) => lifecycle.abortSignal)), |
97 | | - onAdopted: async () => { |
98 | | - handedOff = true; |
99 | | - await adoptAll(); |
100 | | - }, |
101 | | - onDeferred: () => { |
102 | | - handedOff = true; |
103 | | - for (const lifecycle of lifecycles) { |
104 | | - lifecycle.onDeferred(); |
105 | | - } |
106 | | - }, |
107 | | - onAdoptionFinalizing: () => { |
108 | | - for (const lifecycle of lifecycles) { |
109 | | - lifecycle.onAdoptionFinalizing(); |
110 | | - } |
111 | | - }, |
112 | | - onAbandoned: async () => { |
113 | | - handedOff = true; |
114 | | - for (const lifecycle of lifecycles) { |
115 | | - await lifecycle.onAbandoned(); |
116 | | - } |
117 | | - }, |
118 | | - }, |
119 | | - // A gate or deliberate no-dispatch still consumes every merged queue row. |
120 | | - settle: async () => { |
121 | | - if (!handedOff) { |
122 | | - await adoptAll(); |
123 | | - } |
124 | | - }, |
125 | | - abandon: async () => { |
126 | | - if (handedOff) { |
127 | | - return; |
128 | | - } |
129 | | - handedOff = true; |
130 | | - for (const lifecycle of lifecycles) { |
131 | | - await lifecycle.onAbandoned(); |
132 | | - } |
133 | | - }, |
134 | | - }; |
135 | | -} |
136 | | - |
137 | 66 | export function createDiscordMessageDispatcher( |
138 | 67 | params: DiscordMessageHandlerParams, |
139 | 68 | ): DiscordMessageDispatcherWithLifecycle { |
@@ -209,7 +138,9 @@ export function createDiscordMessageDispatcher( |
209 | 138 | if (!last) { |
210 | 139 | return; |
211 | 140 | } |
212 | | - const ingress = buildFlushIngressLifecycle(entries); |
| 141 | + const ingress = fanInChannelIngressLifecycles( |
| 142 | + entries.map((entry) => entry.turnAdoptionLifecycle), |
| 143 | + ); |
213 | 144 | const abortSignal = last.abortSignal; |
214 | 145 | if (abortSignal?.aborted) { |
215 | 146 | await ingress.abandon(abortSignal.reason); |
|
0 commit comments