mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-12 08:27:27 +02:00
fix(post): reuse signed event for retries instead of recreating
Event reuse for retries: - Add lastPublishedEvent state to store the signed event - Store signed event after creation in handlePublish() - Simplify retryRelay() to republish the same signed event - Remove duplicate event creation and signing in retryRelay() - Remove duplicate client tag addition in retryRelay() Benefits: - Same event ID and signature across all relays - More efficient - no need to re-sign - Consistent event across retries - Single source of truth for published event Flow: 1. User publishes - event created, signed, stored 2. Some relays fail - event remains in state 3. User retries - same event republished to failed relay 4. New post overwrites lastPublishedEvent with new event
This commit is contained in:
@@ -41,6 +41,7 @@ export function PostViewer() {
|
||||
const [relayStates, setRelayStates] = useState<RelayPublishState[]>([]);
|
||||
const [selectedRelays, setSelectedRelays] = useState<Set<string>>(new Set());
|
||||
const [isEditorEmpty, setIsEditorEmpty] = useState(true);
|
||||
const [lastPublishedEvent, setLastPublishedEvent] = useState<any>(null);
|
||||
|
||||
// Get active account's write relays from Grimoire state
|
||||
const writeRelays = useMemo(() => {
|
||||
@@ -171,66 +172,13 @@ export function PostViewer() {
|
||||
// Retry publishing to a specific relay
|
||||
const retryRelay = useCallback(
|
||||
async (relayUrl: string) => {
|
||||
if (!editorRef.current) return;
|
||||
|
||||
const serialized = editorRef.current.getSerializedContent();
|
||||
if (!serialized.text.trim()) return;
|
||||
|
||||
// Create the event again
|
||||
if (!canSign || !signer) return;
|
||||
// Reuse the last published event instead of recreating it
|
||||
if (!lastPublishedEvent) {
|
||||
toast.error("No event to retry");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const factory = new EventFactory();
|
||||
factory.setSigner(signer);
|
||||
|
||||
// Build tags array
|
||||
const tags: string[][] = [];
|
||||
|
||||
// Add p tags for mentions
|
||||
for (const pubkey of serialized.mentions) {
|
||||
tags.push(["p", pubkey]);
|
||||
}
|
||||
|
||||
// Add e tags for event references
|
||||
for (const eventId of serialized.eventRefs) {
|
||||
tags.push(["e", eventId]);
|
||||
}
|
||||
|
||||
// Add a tags for address references
|
||||
for (const addr of serialized.addressRefs) {
|
||||
tags.push(["a", `${addr.kind}:${addr.pubkey}:${addr.identifier}`]);
|
||||
}
|
||||
|
||||
// Add client tag
|
||||
tags.push(["client", "grimoire"]);
|
||||
|
||||
// Add emoji tags
|
||||
for (const emoji of serialized.emojiTags) {
|
||||
tags.push(["emoji", emoji.shortcode, emoji.url]);
|
||||
}
|
||||
|
||||
// Add blob attachment tags (imeta)
|
||||
for (const blob of serialized.blobAttachments) {
|
||||
const imetaTag = [
|
||||
"imeta",
|
||||
`url ${blob.url}`,
|
||||
`m ${blob.mimeType}`,
|
||||
`x ${blob.sha256}`,
|
||||
`size ${blob.size}`,
|
||||
];
|
||||
if (blob.server) {
|
||||
imetaTag.push(`server ${blob.server}`);
|
||||
}
|
||||
tags.push(imetaTag);
|
||||
}
|
||||
|
||||
const draft = await factory.build({
|
||||
kind: 1,
|
||||
content: serialized.text.trim(),
|
||||
tags,
|
||||
});
|
||||
const event = await factory.sign(draft);
|
||||
|
||||
// Update status to publishing
|
||||
setRelayStates((prev) =>
|
||||
prev.map((r) =>
|
||||
@@ -240,8 +188,8 @@ export function PostViewer() {
|
||||
),
|
||||
);
|
||||
|
||||
// Try to publish
|
||||
await pool.publish([relayUrl], event);
|
||||
// Republish the same signed event
|
||||
await pool.publish([relayUrl], lastPublishedEvent);
|
||||
|
||||
// Update status to success
|
||||
setRelayStates((prev) =>
|
||||
@@ -272,7 +220,7 @@ export function PostViewer() {
|
||||
);
|
||||
}
|
||||
},
|
||||
[canSign, signer],
|
||||
[lastPublishedEvent],
|
||||
);
|
||||
|
||||
// Publish to selected relays with per-relay status tracking
|
||||
@@ -357,6 +305,9 @@ export function PostViewer() {
|
||||
});
|
||||
const event = await factory.sign(draft);
|
||||
|
||||
// Store the signed event for potential retries
|
||||
setLastPublishedEvent(event);
|
||||
|
||||
// Update relay states - set selected to publishing, keep others as pending
|
||||
setRelayStates((prev) =>
|
||||
prev.map((r) =>
|
||||
@@ -415,6 +366,8 @@ export function PostViewer() {
|
||||
localStorage.removeItem(draftKey);
|
||||
}
|
||||
|
||||
// Don't clear lastPublishedEvent here - keep it for potential retries
|
||||
|
||||
toast.success(
|
||||
`Published to ${selected.length} relay${selected.length > 1 ? "s" : ""}`,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user