midjourney-mcp
Version:
A Model Context Protocol server for Midjourney integration via MJ API
127 lines • 3.96 kB
JavaScript
/**
* Task polling utilities for async operations
*/
export class TaskPoller {
client;
constructor(client) {
this.client = client;
}
/**
* Poll a task until completion or timeout
*/
async pollTask(taskId, options = {}) {
const { maxAttempts = 60, // 5 minutes with 5s intervals
intervalMs = 5000, timeoutMs = 300000, // 5 minutes
} = options;
const startTime = Date.now();
let attempts = 0;
while (attempts < maxAttempts) {
// Check timeout
if (Date.now() - startTime > timeoutMs) {
throw new Error(`Task polling timeout after ${timeoutMs}ms`);
}
try {
const task = await this.client.getTask(taskId);
// Check if task is completed
if (task.status === 'SUCCESS' || task.status === 'FAILURE') {
return task;
}
// If task is still in progress, wait and retry
if (task.status === 'IN_PROGRESS' || task.status === 'SUBMITTED') {
attempts++;
await this.sleep(intervalMs);
continue;
}
// Unknown status, return current state
return task;
}
catch (error) {
attempts++;
// If this is the last attempt, throw the error
if (attempts >= maxAttempts) {
throw error;
}
// Wait before retry
await this.sleep(intervalMs);
}
}
throw new Error(`Task polling failed after ${maxAttempts} attempts`);
}
/**
* Get task status without polling
*/
async getTaskStatus(taskId) {
return this.client.getTask(taskId);
}
/**
* Check if task is completed
*/
isTaskCompleted(task) {
return task.status === 'SUCCESS' || task.status === 'FAILURE';
}
/**
* Check if task is successful
*/
isTaskSuccessful(task) {
return task.status === 'SUCCESS';
}
/**
* Check if task failed
*/
isTaskFailed(task) {
return task.status === 'FAILURE';
}
/**
* Get task progress percentage
*/
getTaskProgress(task) {
if (!task.progress) {
return 0;
}
// Parse progress string like "50%" or "completed"
if (task.progress === 'completed' || task.status === 'SUCCESS') {
return 100;
}
const match = task.progress.match(/(\d+)%/);
if (match && match[1]) {
return parseInt(match[1], 10);
}
return 0;
}
/**
* Format task status for display
*/
formatTaskStatus(task) {
const progress = this.getTaskProgress(task);
const status = task.status || 'UNKNOWN';
let statusText = status.toLowerCase().replace('_', ' ');
if (task.status === 'IN_PROGRESS' && progress > 0) {
statusText += ` (${progress}%)`;
}
if (task.status === 'FAILURE' && task.failReason) {
statusText += `: ${task.failReason}`;
}
return statusText;
}
/**
* Check if task appears to be stuck
*/
isTaskStuck(task) {
if (task.status !== 'IN_PROGRESS' || !task.submitTime) {
return false;
}
const submitTime = new Date(task.submitTime);
const now = new Date();
const durationMs = now.getTime() - submitTime.getTime();
const durationMinutes = Math.floor(durationMs / 60000);
// Consider task stuck if it's been running for more than 15 minutes
return durationMinutes > 15;
}
/**
* Sleep for specified milliseconds
*/
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
//# sourceMappingURL=task-poller.js.map