融合最新主线完美像素修复
保留完美像素逻辑分辨率和External v1契约更新。 合并无限画布恢复事务与共享记忆结论。
This commit is contained in:
@@ -3160,20 +3160,31 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
|
||||
it('retries the exact persisted request without creating a second dialog or operation', async () => {
|
||||
const flushProjectPersistence = vi.fn().mockResolvedValue(undefined);
|
||||
const applyProjectSnapshot = vi.fn();
|
||||
snapImageToPerfectPixelsMock
|
||||
.mockImplementationOnce(async (request: EditorPixelArtSnapInput) =>
|
||||
createMismatchedPerfectPixelResult(request),
|
||||
)
|
||||
.mockImplementationOnce(async (request: EditorPixelArtSnapInput) =>
|
||||
createMismatchedPerfectPixelResult(request),
|
||||
.mockRejectedValueOnce(
|
||||
new ApiClientError({
|
||||
message: '同一完美像素操作已有其它权威结果,请先读取项目状态对账。',
|
||||
status: 409,
|
||||
code: 'HTTP_409',
|
||||
details: { operationResultAlreadyExists: true },
|
||||
}),
|
||||
);
|
||||
loadEditorProjectMock.mockImplementation(async () => {
|
||||
const request = snapImageToPerfectPixelsMock.mock.calls.at(-1)?.[0] as
|
||||
| EditorPixelArtSnapInput
|
||||
| undefined;
|
||||
return createConflictingPerfectPixelProject(
|
||||
request!.canvasCompletion.dialogId,
|
||||
);
|
||||
return snapImageToPerfectPixelsMock.mock.calls.length === 1
|
||||
? createConflictingPerfectPixelProject(
|
||||
request!.canvasCompletion.dialogId,
|
||||
)
|
||||
: createPerfectPixelProject(
|
||||
request!.canvasCompletion.dialogId,
|
||||
'applied',
|
||||
);
|
||||
});
|
||||
render(
|
||||
<GenerationWorkflowHarness
|
||||
@@ -3184,7 +3195,7 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
src: '/generated-images/editor/source.png',
|
||||
}),
|
||||
]}
|
||||
applyProjectSnapshot={vi.fn()}
|
||||
applyProjectSnapshot={applyProjectSnapshot}
|
||||
flushProjectPersistence={flushProjectPersistence}
|
||||
/>,
|
||||
);
|
||||
@@ -3241,6 +3252,12 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
expect(flushProjectPersistence).toHaveBeenNthCalledWith(2, {
|
||||
preferLatestGenerationDialogs: true,
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(applyProjectSnapshot).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ projectId: 'project-1' }),
|
||||
{ type: 'perfect-pixel', count: 1 },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('anchors the first submission reconciliation window at POST time when the pre-POST flush is slow', async () => {
|
||||
@@ -3724,7 +3741,10 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('reconciles a responded failure that the server marked as post-persistence', async () => {
|
||||
it.each([
|
||||
['post-persistence', { resultPersistenceStarted: true }],
|
||||
['an existing operation result', { operationResultAlreadyExists: true }],
|
||||
])('reconciles a responded failure marked as %s', async (_label, details) => {
|
||||
const applyProjectSnapshot = vi.fn();
|
||||
const refreshAssetLibrary = vi.fn().mockResolvedValue(undefined);
|
||||
let operationId = '';
|
||||
@@ -3736,7 +3756,7 @@ describe('useImageCanvasGenerationWorkflow', () => {
|
||||
message: '画布版本冲突。',
|
||||
status: 409,
|
||||
code: 'HTTP_409',
|
||||
details: { resultPersistenceStarted: true },
|
||||
details,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -2781,6 +2781,10 @@ export function useImageCanvasGenerationWorkflow({
|
||||
error instanceof ApiClientError &&
|
||||
(error.details as { resultPersistenceStarted?: unknown } | null)
|
||||
?.resultPersistenceStarted === true;
|
||||
const operationResultAlreadyExists =
|
||||
error instanceof ApiClientError &&
|
||||
(error.details as { operationResultAlreadyExists?: unknown } | null)
|
||||
?.operationResultAlreadyExists === true;
|
||||
const outcomeMayBePersisted =
|
||||
perfectPixelPostAttempted &&
|
||||
Boolean(perfectPixelDialogId) &&
|
||||
@@ -2790,6 +2794,9 @@ export function useImageCanvasGenerationWorkflow({
|
||||
// 而此时 api-server 可能已经走完 OSS PUT 与落库。必须算作未知结果去对账。
|
||||
(!(error instanceof ApiClientError) ||
|
||||
persistenceMayHaveStarted ||
|
||||
// 中文注释:跨算法版本护栏在本请求 PUT 前发现同 operation 已有权威结果;它不应
|
||||
// 冒充 resultPersistenceStarted,但同样必须读取项目事实完成收口。
|
||||
operationResultAlreadyExists ||
|
||||
isGatewayUnknownOutcomeError(error));
|
||||
let reconciledMessage: string | undefined;
|
||||
let keepPendingConfirmation = false;
|
||||
@@ -3023,10 +3030,15 @@ export function useImageCanvasGenerationWorkflow({
|
||||
error instanceof ApiClientError &&
|
||||
(error.details as { resultPersistenceStarted?: unknown } | null)
|
||||
?.resultPersistenceStarted === true;
|
||||
const operationResultAlreadyExists =
|
||||
error instanceof ApiClientError &&
|
||||
(error.details as { operationResultAlreadyExists?: unknown } | null)
|
||||
?.operationResultAlreadyExists === true;
|
||||
const outcomeMayBePersisted =
|
||||
postAttempted &&
|
||||
(!(error instanceof ApiClientError) ||
|
||||
persistenceMayHaveStarted ||
|
||||
operationResultAlreadyExists ||
|
||||
isGatewayUnknownOutcomeError(error));
|
||||
if (outcomeMayBePersisted) {
|
||||
const verdict = await reconcilePerfectPixelProject(
|
||||
|
||||
Reference in New Issue
Block a user