289 lines
8.6 KiB
TypeScript
289 lines
8.6 KiB
TypeScript
|
|
/**
|
|||
|
|
* [MOCK-015] 执行结果模块DataSource
|
|||
|
|
* AI注意: 这是Mock实现,不是真实业务逻辑
|
|||
|
|
* 仅在USE_MOCK=true时启用 */
|
|||
|
|
|
|||
|
|
export interface ExecutionResult {
|
|||
|
|
id: string;
|
|||
|
|
taskId: string;
|
|||
|
|
actionType: string;
|
|||
|
|
status: 'success' | 'failed' | 'in_progress' | 'pending';
|
|||
|
|
startTime: Date;
|
|||
|
|
endTime?: Date;
|
|||
|
|
duration?: number;
|
|||
|
|
clientId: string;
|
|||
|
|
result: {
|
|||
|
|
success: boolean;
|
|||
|
|
message: string;
|
|||
|
|
data?: any;
|
|||
|
|
error?: string;
|
|||
|
|
};
|
|||
|
|
logs: {
|
|||
|
|
timestamp: Date;
|
|||
|
|
level: 'info' | 'warn' | 'error';
|
|||
|
|
message: string;
|
|||
|
|
}[];
|
|||
|
|
metadata: {
|
|||
|
|
platform: string;
|
|||
|
|
userId: string;
|
|||
|
|
correlationId: string;
|
|||
|
|
attempt: number;
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface StatData {
|
|||
|
|
total: number;
|
|||
|
|
success: number;
|
|||
|
|
failed: number;
|
|||
|
|
inProgress: number;
|
|||
|
|
successRate: number;
|
|||
|
|
avgDuration: number;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export interface ExecutionResultDataSource {
|
|||
|
|
fetchResults(params?: {
|
|||
|
|
status?: string;
|
|||
|
|
actionType?: string;
|
|||
|
|
startDate?: string;
|
|||
|
|
endDate?: string;
|
|||
|
|
search?: string;
|
|||
|
|
}): Promise<ExecutionResult[]>;
|
|||
|
|
getResult(id: string): Promise<ExecutionResult | null>;
|
|||
|
|
getExecutionStats(): Promise<StatData>;
|
|||
|
|
exportResult(id: string): Promise<boolean>;
|
|||
|
|
retryExecution(id: string): Promise<ExecutionResult | null>;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export class ExecutionResultDataSourceImpl implements ExecutionResultDataSource {
|
|||
|
|
private results: ExecutionResult[] = [
|
|||
|
|
{
|
|||
|
|
id: '1',
|
|||
|
|
taskId: 'task-001',
|
|||
|
|
actionType: 'price_update',
|
|||
|
|
status: 'success',
|
|||
|
|
startTime: new Date(Date.now() - 3600000),
|
|||
|
|
endTime: new Date(Date.now() - 3540000),
|
|||
|
|
duration: 60,
|
|||
|
|
clientId: 'localhost:8080',
|
|||
|
|
result: {
|
|||
|
|
success: true,
|
|||
|
|
message: 'Price updated successfully',
|
|||
|
|
data: {
|
|||
|
|
productId: 'prod-123',
|
|||
|
|
oldPrice: 100,
|
|||
|
|
newPrice: 90,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
logs: [
|
|||
|
|
{ timestamp: new Date(Date.now() - 3600000), level: 'info', message: 'Starting price update' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 3570000), level: 'info', message: 'Fetching product data' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 3550000), level: 'info', message: 'Updating price' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 3540000), level: 'info', message: 'Price updated successfully' },
|
|||
|
|
],
|
|||
|
|
metadata: {
|
|||
|
|
platform: 'amazon',
|
|||
|
|
userId: 'user-001',
|
|||
|
|
correlationId: 'corr-001',
|
|||
|
|
attempt: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '2',
|
|||
|
|
taskId: 'task-002',
|
|||
|
|
actionType: 'inventory_sync',
|
|||
|
|
status: 'failed',
|
|||
|
|
startTime: new Date(Date.now() - 7200000),
|
|||
|
|
endTime: new Date(Date.now() - 7140000),
|
|||
|
|
duration: 60,
|
|||
|
|
clientId: 'localhost:8081',
|
|||
|
|
result: {
|
|||
|
|
success: false,
|
|||
|
|
message: 'Inventory sync failed',
|
|||
|
|
error: 'Connection timeout',
|
|||
|
|
},
|
|||
|
|
logs: [
|
|||
|
|
{ timestamp: new Date(Date.now() - 7200000), level: 'info', message: 'Starting inventory sync' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 7180000), level: 'info', message: 'Connecting to inventory service' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 7140000), level: 'error', message: 'Connection timeout' },
|
|||
|
|
],
|
|||
|
|
metadata: {
|
|||
|
|
platform: 'shopify',
|
|||
|
|
userId: 'user-002',
|
|||
|
|
correlationId: 'corr-002',
|
|||
|
|
attempt: 2,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '3',
|
|||
|
|
taskId: 'task-003',
|
|||
|
|
actionType: 'order_processing',
|
|||
|
|
status: 'in_progress',
|
|||
|
|
startTime: new Date(Date.now() - 1800000),
|
|||
|
|
clientId: 'localhost:8080',
|
|||
|
|
result: {
|
|||
|
|
success: false,
|
|||
|
|
message: 'Processing...',
|
|||
|
|
},
|
|||
|
|
logs: [
|
|||
|
|
{ timestamp: new Date(Date.now() - 1800000), level: 'info', message: 'Starting order processing' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 1740000), level: 'info', message: 'Fetching orders' },
|
|||
|
|
],
|
|||
|
|
metadata: {
|
|||
|
|
platform: 'ebay',
|
|||
|
|
userId: 'user-001',
|
|||
|
|
correlationId: 'corr-003',
|
|||
|
|
attempt: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
id: '4',
|
|||
|
|
taskId: 'task-004',
|
|||
|
|
actionType: 'price_update',
|
|||
|
|
status: 'success',
|
|||
|
|
startTime: new Date(Date.now() - 10800000),
|
|||
|
|
endTime: new Date(Date.now() - 10740000),
|
|||
|
|
duration: 60,
|
|||
|
|
clientId: 'localhost:8082',
|
|||
|
|
result: {
|
|||
|
|
success: true,
|
|||
|
|
message: 'Price updated successfully',
|
|||
|
|
data: {
|
|||
|
|
productId: 'prod-456',
|
|||
|
|
oldPrice: 200,
|
|||
|
|
newPrice: 180,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
logs: [
|
|||
|
|
{ timestamp: new Date(Date.now() - 10800000), level: 'info', message: 'Starting price update' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 10770000), level: 'info', message: 'Fetching product data' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 10750000), level: 'info', message: 'Updating price' },
|
|||
|
|
{ timestamp: new Date(Date.now() - 10740000), level: 'info', message: 'Price updated successfully' },
|
|||
|
|
],
|
|||
|
|
metadata: {
|
|||
|
|
platform: 'amazon',
|
|||
|
|
userId: 'user-003',
|
|||
|
|
correlationId: 'corr-004',
|
|||
|
|
attempt: 1,
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
async fetchResults(params?: {
|
|||
|
|
status?: string;
|
|||
|
|
actionType?: string;
|
|||
|
|
startDate?: string;
|
|||
|
|
endDate?: string;
|
|||
|
|
search?: string;
|
|||
|
|
}): Promise<ExecutionResult[]> {
|
|||
|
|
// 模拟API延迟
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|||
|
|
|
|||
|
|
let filteredResults = [...this.results];
|
|||
|
|
|
|||
|
|
if (params?.status && params.status !== 'all') {
|
|||
|
|
filteredResults = filteredResults.filter(result => result.status === params.status);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (params?.actionType && params.actionType !== 'all') {
|
|||
|
|
filteredResults = filteredResults.filter(result => result.actionType === params.actionType);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (params?.search) {
|
|||
|
|
const searchLower = params.search.toLowerCase();
|
|||
|
|
filteredResults = filteredResults.filter(result =>
|
|||
|
|
result.taskId.toLowerCase().includes(searchLower) ||
|
|||
|
|
result.actionType.toLowerCase().includes(searchLower) ||
|
|||
|
|
result.clientId.toLowerCase().includes(searchLower) ||
|
|||
|
|
result.metadata.platform.toLowerCase().includes(searchLower)
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (params?.startDate && params?.endDate) {
|
|||
|
|
const startDate = new Date(params.startDate).getTime();
|
|||
|
|
const endDate = new Date(params.endDate).getTime();
|
|||
|
|
filteredResults = filteredResults.filter(result => {
|
|||
|
|
const resultTime = result.startTime.getTime();
|
|||
|
|
return resultTime >= startDate && resultTime <= endDate;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return filteredResults;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getResult(id: string): Promise<ExecutionResult | null> {
|
|||
|
|
// 模拟API延迟
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|||
|
|
|
|||
|
|
const result = this.results.find(result => result.id === id);
|
|||
|
|
return result || null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async getExecutionStats(): Promise<StatData> {
|
|||
|
|
// 模拟API延迟
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|||
|
|
|
|||
|
|
const total = this.results.length;
|
|||
|
|
const success = this.results.filter(r => r.status === 'success').length;
|
|||
|
|
const failed = this.results.filter(r => r.status === 'failed').length;
|
|||
|
|
const inProgress = this.results.filter(r => r.status === 'in_progress').length;
|
|||
|
|
const successRate = total > 0 ? (success / total) * 100 : 0;
|
|||
|
|
const completedResults = this.results.filter(r => r.duration);
|
|||
|
|
const avgDuration = completedResults.length > 0
|
|||
|
|
? completedResults.reduce((sum, r) => sum + (r.duration || 0), 0) / completedResults.length
|
|||
|
|
: 0;
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
total,
|
|||
|
|
success,
|
|||
|
|
failed,
|
|||
|
|
inProgress,
|
|||
|
|
successRate,
|
|||
|
|
avgDuration,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async exportResult(id: string): Promise<boolean> {
|
|||
|
|
// 模拟API延迟
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|||
|
|
|
|||
|
|
const result = this.results.find(result => result.id === id);
|
|||
|
|
return !!result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async retryExecution(id: string): Promise<ExecutionResult | null> {
|
|||
|
|
// 模拟API延迟
|
|||
|
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|||
|
|
|
|||
|
|
const resultIndex = this.results.findIndex(result => result.id === id);
|
|||
|
|
if (resultIndex === -1) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const originalResult = this.results[resultIndex];
|
|||
|
|
const newResult: ExecutionResult = {
|
|||
|
|
...originalResult,
|
|||
|
|
id: `${Date.now()}`,
|
|||
|
|
status: 'in_progress',
|
|||
|
|
startTime: new Date(),
|
|||
|
|
endTime: undefined,
|
|||
|
|
duration: undefined,
|
|||
|
|
result: {
|
|||
|
|
success: false,
|
|||
|
|
message: 'Processing...',
|
|||
|
|
},
|
|||
|
|
logs: [
|
|||
|
|
{ timestamp: new Date(), level: 'info', message: `Retrying execution for task ${originalResult.taskId}` },
|
|||
|
|
],
|
|||
|
|
metadata: {
|
|||
|
|
...originalResult.metadata,
|
|||
|
|
attempt: originalResult.metadata.attempt + 1,
|
|||
|
|
correlationId: `corr-${Date.now()}`,
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.results.unshift(newResult);
|
|||
|
|
return newResult;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export const executionResultDataSource = new ExecutionResultDataSourceImpl();
|