polling jobs implemented (#492)

Co-authored-by: Michael Chung <michaelchung@michaels-mbp-2.home>
This commit is contained in:
ArEnScandMichael Chung authored and GitHub committed 2025-04-09 15:15:13 -04:00
1 parent e8beb2ff8c
commit 06a0a8070d
3 files changed
+142 -43

No files matched your search

+31 -11
View File
@@ -148,7 +148,7 @@ export class ApiManager {
formData.append("file", blob);
}
console.log(`HELLO${formData}`);
// console.log(`HELLO${formData}`);
return this.fetchMultipartFormData<T>(endpoint, {
method: "POST",
headers: {
@@ -248,7 +248,6 @@ export class Api extends ApiManager {
formData.append("scene_media_token", sceneMediaToken);
}
// for now ...
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
formData.append("uuid_idempotency_token", uuidIdempotencyToken); // Added uuid_idempotency_token
@@ -262,9 +261,7 @@ export class Api extends ApiManager {
});
const postResponse = await response.json();
console.log(postResponse);
let result: { success: boolean; data?: string; errorMessage?: string };
if (postResponse.success) {
@@ -276,7 +273,7 @@ export class Api extends ApiManager {
} else {
result = {
success: false,
errorMessage: postResponse.BadInput,
errorMessage: "Failed to generate snapshot.",
};
}
@@ -293,7 +290,7 @@ export class Api extends ApiManager {
additionalImages?: string[];
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/prompt`;
// for now ...
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
const body = {
uuid_idempotency_token: uuidIdempotencyToken,
@@ -317,11 +314,13 @@ export class Api extends ApiManager {
// Check if the response is successful
const isSuccess = postResponse.success ?? false;
// Prepare the result object
console.log("postResponse FOR ENQUEUE IMAGE GENERATION");
console.log(postResponse);
const result = {
success: isSuccess,
data: isSuccess ? postResponse.job_token : undefined,
data: isSuccess ? postResponse.inference_job_token : undefined,
errorMessage: isSuccess ? undefined : postResponse.BadInput,
};
@@ -330,14 +329,21 @@ export class Api extends ApiManager {
public async pollJobSession(jobToken: string): Promise<
ApiResponse<{
status: string;
job_token: string;
request: {
maybe_model_title: string;
};
status: {
status: string;
progress_percentage: number;
};
result: {
generated_images?: string[];
error?: string;
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session/${jobToken}`;
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -351,17 +357,31 @@ export class Api extends ApiManager {
endpoint,
});
console.log("response FROM JOBS");
console.log(response);
const success = response.success ?? false;
const status = response.status ?? "";
const result = response.result ?? {
generated_images: [],
error: undefined,
};
const errorMessage = response.BadInput;
return {
success,
data: { status, result },
data: {
result,
job_token: jobToken,
request: {
maybe_model_title: "Image Generation",
},
status: {
status: status.toLowerCase(),
progress_percentage: 0,
},
},
errorMessage,
};
}
@@ -1,6 +1,7 @@
import { useState, useRef, useEffect } from "react";
import { invoke } from "@tauri-apps/api/core";
import { useSignals } from "@preact/signals-react/runtime";
import { toast } from "sonner";
import {
UploaderStates,
// UploaderState,
@@ -11,7 +12,7 @@ import { PopoverMenu } from "~/components/reusable/Popover";
import { Tooltip } from "~/components/reusable/Tooltip";
import { Button } from "~/components/reusable/Button";
import { ToggleButton } from "~/components/reusable/ToggleButton";
import { Toaster } from "~/components/ui/Toast";
import {
faMessageXmark,
faMessageCheck,
@@ -245,20 +246,25 @@ export const PromptBox = () => {
additionalImages: referenceImages.map((image) => image.mediaToken),
});
console.log("Response:", response);
if (response.success === true) {
console.error("Successfully enqueued image generation.");
if (response.data) {
console.log("Response:", response.data);
setJobToken(response.data);
}
return;
} else {
console.log("Image generation Not Successful.");
toast.error("Failed to generate image. Please try again.");
}
}
} catch (error) {
console.error("Error during image generation:", error);
toast.error(
"An error occurred while generating the image. Please try again.",
);
} finally {
setisEnqueueing(false);
}
@@ -5,6 +5,7 @@ import { PopoverMenu } from "~/components/reusable/Popover";
import { CompletedCard } from "./CompletedCard";
import { InProgressCard } from "./InProgressCard";
import { useJobContext } from "~/components/JobContext";
import { Api } from "~/KonvaApp/Api";
// Dummy data types
interface CompletedItem {
token: string;
@@ -40,28 +41,28 @@ const dummyCompletedItems: CompletedItem[] = [
},
];
const dummyJobs: ActiveJob[] = [
{
job_token: "job1",
request: {
maybe_model_title: "In Progress Job 1",
},
status: {
status: "STARTED",
progress_percentage: 45,
},
},
{
job_token: "job2",
request: {
maybe_model_title: "In Progress Job 2",
},
status: {
status: "PENDING",
progress_percentage: 0,
},
},
];
// const dummyJobs: ActiveJob[] = [
// {
// job_token: "job1",
// request: {
// maybe_model_title: "In Progress Job 1",
// },
// status: {
// status: "STARTED",
// progress_percentage: 45,
// },
// },
// {
// job_token: "job2",
// request: {
// maybe_model_title: "In Progress Job 2",
// },
// status: {
// status: "PENDING",
// progress_percentage: 0,
// },
// },
// ];
export function Activity() {
const { jobToken, setJobToken } = useJobContext();
@@ -71,26 +72,98 @@ export function Activity() {
// Dummy polling function
useEffect(() => {
const pollData = () => {
// Simulate API calls
const pollData = async () => {
if (jobToken) {
console.log("Current Job Token:", jobToken);
const api = new Api();
const job = await api.pollJobSession(jobToken);
console.log("Job response:", job);
if (job.success && job.data) {
const { status, progress_percentage } = job.data.status;
const { job_token } = job.data;
console.log("Job status:", status);
console.log("Progress percentage:", progress_percentage);
console.log("Job token:", job_token);
// Update jobs with real job data
if (
status.toLowerCase() === "completed" ||
status.toLowerCase() === "failed"
) {
// If job is completed or failed, remove it from active jobs
setJobs((prevJobs) =>
prevJobs.filter((j) => j.job_token !== job_token),
);
// Add to completed items if it was successful
if (
status.toLowerCase() === "completed" &&
job.data.result.generated_images
) {
const newCompletedItem: CompletedItem = {
id: job_token,
title: job.data.request.maybe_model_title || "Image Generation",
timestamp: new Date().toISOString(),
type: "image",
imageUrl: job.data.result.generated_images[0] || "",
};
setCompletedItems((prev) => [newCompletedItem, ...prev]);
}
} else {
// Update or add the job to the active jobs list
const updatedJob: ActiveJob = {
job_token,
request: {
maybe_model_title:
job.data.request.maybe_model_title || "Image Generation",
},
status: {
status: status.toUpperCase(),
progress_percentage: progress_percentage || 0,
},
};
setJobs((prevJobs) => {
const existingJobIndex = prevJobs.findIndex(
(j) => j.job_token === job_token,
);
if (existingJobIndex >= 0) {
// Update existing job
const newJobs = [...prevJobs];
newJobs[existingJobIndex] = updatedJob;
return newJobs;
} else {
// Add new job
return [updatedJob, ...prevJobs];
}
});
}
} else {
console.error("Failed to fetch job status:", job.errorMessage);
}
} else {
console.log("No Job Token available.");
}
setCompletedItems(dummyCompletedItems);
setJobs(dummyJobs);
setLoading(false);
if (jobs.length === 0) {
setLoading(false);
}
};
// Initial load
// Initial call to pollData
pollData();
// Set up polling interval (every 5 seconds)
const interval = setInterval(pollData, 5000);
const interval = setInterval(async () => {
await pollData();
}, 5000);
return () => clearInterval(interval);
}, []);
}, [jobToken]);
return (
<PopoverMenu