Fix cross-account candidate delivery
This commit is contained in:
1 parent
df35648920
commit
deaf86c364
2 files changed
+64
No files matched your search
@@ -52,6 +52,25 @@ export interface ConcreteRuntimeFactoryOptions {
|
|||||||
isBotRunning?: () => boolean;
|
isBotRunning?: () => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function materializePreparedPostForAccount(
|
||||||
|
resources: Pick<RedditAccountRuntimeResources, 'postsRepo' | 'redditApi'>,
|
||||||
|
processed: ProcessedPost,
|
||||||
|
now: number = Date.now(),
|
||||||
|
): void {
|
||||||
|
const { post } = processed;
|
||||||
|
resources.postsRepo.insertIfAbsent({
|
||||||
|
id: post.id,
|
||||||
|
subreddit: post.subreddit,
|
||||||
|
author: post.author,
|
||||||
|
title: post.title,
|
||||||
|
postUrl: resources.redditApi.getPostUrl(post),
|
||||||
|
imageUrl: processed.sourceType === 'image' ? resources.redditApi.getImageUrl(post) : null,
|
||||||
|
postCreatedAt: post.created_utc * 1_000,
|
||||||
|
processedAt: now,
|
||||||
|
});
|
||||||
|
resources.postsRepo.updateAnalysis(post.id, processed.imageAnalysis, processed.generatedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
export function createConcreteRedditAccountRuntimeFactory(
|
export function createConcreteRedditAccountRuntimeFactory(
|
||||||
options: ConcreteRuntimeFactoryOptions,
|
options: ConcreteRuntimeFactoryOptions,
|
||||||
): RedditAccountRuntimeFactory {
|
): RedditAccountRuntimeFactory {
|
||||||
@@ -326,6 +345,13 @@ class AccountRuntimeLoop {
|
|||||||
if (signal?.aborted) {
|
if (signal?.aborted) {
|
||||||
return { status: 'retryable', reason: 'Delivery interrupted by shutdown', retryAt: Date.now() + 5_000 };
|
return { status: 'retryable', reason: 'Delivery interrupted by shutdown', retryAt: Date.now() + 5_000 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Preparation may have been performed by a different authenticated
|
||||||
|
// scanner. Sent messages are account-scoped and reference that account's
|
||||||
|
// processed-post row, so materialise the prepared candidate locally before
|
||||||
|
// performing the irreversible remote chat creation.
|
||||||
|
materializePreparedPostForAccount(this.resources, processed);
|
||||||
|
|
||||||
return rateLimiter.throttle(async (): Promise<PreparedDeliveryResult> => {
|
return rateLimiter.throttle(async (): Promise<PreparedDeliveryResult> => {
|
||||||
if (this.config.browser.dryRun) {
|
if (this.config.browser.dryRun) {
|
||||||
const reason = 'Dry run: message prepared but not sent';
|
const reason = 'Dry run: message prepared but not sent';
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { describe, expect, it, vi } from 'vitest';
|
||||||
|
import type { RedditPost } from '../src/reddit/api.js';
|
||||||
|
import type { RedditAccountRuntimeResources } from '../src/services/reddit-account-runtime.js';
|
||||||
|
import { materializePreparedPostForAccount } from '../src/services/reddit-account-runtime-builder.js';
|
||||||
|
import type { ProcessedPost } from '../src/services/processor.js';
|
||||||
|
|
||||||
|
describe('materializePreparedPostForAccount', () => {
|
||||||
|
it('creates the sending account post row before message persistence', () => {
|
||||||
|
const post: RedditPost = {
|
||||||
|
id: 'post-1', subreddit: 'test', author: 'alice', author_fullname: 't2_alice',
|
||||||
|
title: 'title', url: 'https://example.com/image.jpg', permalink: '/r/test/post-1',
|
||||||
|
thumbnail: '', is_self: false, created_utc: 123, over_18: true, spoiler: false,
|
||||||
|
};
|
||||||
|
const processed: ProcessedPost = {
|
||||||
|
post, imageAnalysis: 'analysis', detectedGender: 'female', generatedMessage: 'message',
|
||||||
|
strategyId: null, experimentId: null, promptVersion: null, selectionReason: null,
|
||||||
|
modelId: 'model', sourceType: 'image', toneId: 'default', scripted: false,
|
||||||
|
};
|
||||||
|
const insertIfAbsent = vi.fn();
|
||||||
|
const updateAnalysis = vi.fn();
|
||||||
|
const resources = {
|
||||||
|
postsRepo: { insertIfAbsent, updateAnalysis },
|
||||||
|
redditApi: {
|
||||||
|
getPostUrl: () => 'https://reddit.example/post-1',
|
||||||
|
getImageUrl: () => 'https://reddit.example/image.jpg',
|
||||||
|
},
|
||||||
|
} as unknown as Pick<RedditAccountRuntimeResources, 'postsRepo' | 'redditApi'>;
|
||||||
|
|
||||||
|
materializePreparedPostForAccount(resources, processed, 456);
|
||||||
|
|
||||||
|
expect(insertIfAbsent).toHaveBeenCalledWith({
|
||||||
|
id: 'post-1', subreddit: 'test', author: 'alice', title: 'title',
|
||||||
|
postUrl: 'https://reddit.example/post-1', imageUrl: 'https://reddit.example/image.jpg',
|
||||||
|
postCreatedAt: 123_000, processedAt: 456,
|
||||||
|
});
|
||||||
|
expect(updateAnalysis).toHaveBeenCalledWith('post-1', 'analysis', 'message');
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user