11import { DifferV3 } from '@api7/adc-differ' ;
22import * as ADCSDK from '@api7/adc-sdk' ;
33import { HttpAgent , HttpOptions , HttpsAgent } from 'agentkeepalive' ;
4+ import { AxiosResponse } from 'axios' ;
45import type { RequestHandler } from 'express' ;
56import { omit , toString } from 'lodash' ;
67import { lastValueFrom , toArray } from 'rxjs' ;
@@ -127,45 +128,15 @@ export const syncHandler: RequestHandler<
127128 ) ;
128129 const successes = results . filter ( ( result ) => result . success ) ;
129130 const faileds = results . filter ( ( result ) => ! result . success ) ;
130- const simplifyEvent = ( event : ADCSDK . Event ) =>
131- omit ( event , [ 'diff' , 'oldValue' , 'newValue' , 'subEvents' ] ) ;
132- const output = {
133- status :
134- results . length === successes . length
135- ? 'success'
136- : results . length === faileds . length
137- ? 'all_failed'
138- : 'partial_failure' ,
139- total_resources : results . length ,
140- success_count : successes . length ,
141- failed_count : faileds . length ,
142- success : [
143- ...successes . map ( ( { event, axiosResponse, server } ) => ( {
144- server,
145- event : simplifyEvent ( event ) ,
146- synced_at : new Date (
147- axiosResponse ?. headers ?. date ?? new Date ( ) ,
148- ) . toISOString ( ) ,
149- } ) ) ,
150- ] ,
151- failed : [
152- ...faileds . map ( ( { event, error, axiosResponse, server } ) => ( {
153- server,
154- event : simplifyEvent ( event ) ,
155- failed_at : new Date (
156- axiosResponse ?. headers ?. date ?? new Date ( ) ,
157- ) . toISOString ( ) ,
158- reason : error . message ,
159- ...( axiosResponse && {
160- response : {
161- status : axiosResponse . status ,
162- headers : axiosResponse . headers ,
163- data : axiosResponse . data ,
164- } ,
165- } ) ,
166- } ) ) ,
167- ] ,
168- } ;
131+
132+ const output =
133+ task . opts . backend !== 'apisix-standalone'
134+ ? generateOutput ( [ results , successes , faileds ] )
135+ : generateOutputForAPISIXStandalone ( diff , [
136+ results ,
137+ successes ,
138+ faileds ,
139+ ] ) ;
169140
170141 logger . log ( {
171142 level : 'debug' ,
@@ -186,3 +157,110 @@ export const syncHandler: RequestHandler<
186157 } ) ;
187158 }
188159} ;
160+
161+ const simplifyEvent = ( event : ADCSDK . Event ) =>
162+ omit ( event , [ 'diff' , 'oldValue' , 'newValue' , 'subEvents' ] ) ;
163+
164+ const formatAxiosResponse = ( axiosResponse : AxiosResponse ) => ( {
165+ response : {
166+ status : axiosResponse . status ,
167+ headers : axiosResponse . headers ,
168+ data : axiosResponse . data ,
169+ } ,
170+ request : {
171+ url : axiosResponse . config . url ,
172+ method : axiosResponse . config . method ,
173+ headers :
174+ ( ( axiosResponse . config . headers [ 'X-API-KEY' ] = '*****' ) ,
175+ axiosResponse . config . headers ) ,
176+ data : axiosResponse . config . data ,
177+ } ,
178+ } ) ;
179+
180+ const generateOutput = ( [ results , successes , faileds ] : [
181+ Array < ADCSDK . BackendSyncResult > ,
182+ Array < ADCSDK . BackendSyncResult > ,
183+ Array < ADCSDK . BackendSyncResult > ,
184+ ] ) => {
185+ const date = new Date ( ) ;
186+ return {
187+ status :
188+ results . length === successes . length
189+ ? 'success'
190+ : results . length === faileds . length
191+ ? 'all_failed'
192+ : 'partial_failure' ,
193+ total_resources : results . length ,
194+ success_count : successes . length ,
195+ failed_count : faileds . length ,
196+ success : [
197+ ...successes . map ( ( { event, axiosResponse, server } ) => ( {
198+ server,
199+ event : simplifyEvent ( event ) ,
200+ synced_at : new Date ( axiosResponse ?. headers ?. date ?? date ) . toISOString ( ) ,
201+ } ) ) ,
202+ ] ,
203+ failed : [
204+ ...faileds . map ( ( { event, error, axiosResponse, server } ) => ( {
205+ server,
206+ event : simplifyEvent ( event ) ,
207+ failed_at : new Date ( axiosResponse ?. headers ?. date ?? date ) . toISOString ( ) ,
208+ reason : error . message ,
209+ ...( axiosResponse && formatAxiosResponse ( axiosResponse ) ) ,
210+ } ) ) ,
211+ ] ,
212+ } ;
213+ } ;
214+
215+ /**
216+ * The `sync` of the APISIX Standalone backend returns whether sync on the endpoint succeeded or failed,
217+ * while other backends should return the synchronization success status for each individual Event.
218+ * This represents a significant difference in backend behavior, as the APISIX Standalone backend
219+ * always initiates only one request regardless of how many Events require synchronization.
220+ *
221+ * According to the standard of the ADC server sync API, we will use the `success` array to store
222+ * all events and add an additional `endpoint_status` to track the success of synchronization
223+ * across each backend.
224+ * @param events
225+ * @param results
226+ * @returns
227+ */
228+ const generateOutputForAPISIXStandalone = (
229+ events : Array < ADCSDK . Event > ,
230+ [ results , successes , faileds ] : [
231+ Array < ADCSDK . BackendSyncResult > ,
232+ Array < ADCSDK . BackendSyncResult > ,
233+ Array < ADCSDK . BackendSyncResult > ,
234+ ] ,
235+ ) => {
236+ const date = new Date ( ) ;
237+ return {
238+ status :
239+ results . length === successes . length
240+ ? 'success'
241+ : results . length === faileds . length
242+ ? 'all_failed'
243+ : 'partial_failure' ,
244+ total_resources : 0 ,
245+ success_count : successes . length ,
246+ failed_count : faileds . length ,
247+ success : [
248+ ...events . map ( ( event ) => ( {
249+ event : simplifyEvent ( event ) ,
250+ synced_at : date . toISOString ( ) ,
251+ } ) ) ,
252+ ] ,
253+ failed : [ ] ,
254+ endpoint_status : results . map ( ( result ) => {
255+ return {
256+ server : result . server ,
257+ success : result . success ,
258+ reason : result ?. error ?. message ,
259+ requested_at : new Date (
260+ result . axiosResponse ?. headers ?. date ?? date ,
261+ ) . toISOString ( ) ,
262+ ...( result . axiosResponse && formatAxiosResponse ( result . axiosResponse ) ) ,
263+ } ;
264+ } ) ,
265+ } ;
266+ } ;
0 commit comments