Skip to content

Commit

Permalink
fix: ensures autosaves run sequentially rather than ever in parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
jmikrut committed Dec 7, 2024
1 parent 1fdc7cc commit b9859e9
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions packages/ui/src/elements/Autosave/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { ClientCollectionConfig, ClientGlobalConfig } from 'payload'

import { versionDefaults } from 'payload/shared'
import React, { useEffect, useRef, useState } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import { toast } from 'sonner'

import {
Expand Down Expand Up @@ -64,6 +64,9 @@ export const Autosave: React.FC<Props> = ({ id, collection, global: globalDoc })
interval = versionsConfig.drafts.autosave.interval
}

const [queue, setQueue] = useState<(() => Promise<void>)[]>([])
const [isProcessing, setIsProcessing] = useState(false)

const [saving, setSaving] = useState(false)
const debouncedFields = useDebounce(fields, interval)
const modified = useDebounce(formModified, interval)
Expand All @@ -88,6 +91,32 @@ export const Autosave: React.FC<Props> = ({ id, collection, global: globalDoc })
// can always retrieve the most to date locale
localeRef.current = locale

// Function to process the queue
const processQueue = useCallback(async () => {
if (isProcessing || queue.length === 0) {
return
}

setIsProcessing(true)
const currentTask = queue[0]

try {
await currentTask()
} catch (error) {
console.error('Error autosaving:', error)
} finally {
setQueue((prevQueue) => prevQueue.slice(1))
setIsProcessing(false)
}
}, [isProcessing, queue])

// Process the queue whenever it changes
useEffect(() => {
if (!isProcessing) {
void processQueue()
}
}, [queue, isProcessing, processQueue])

// When debounced fields change, autosave
useIgnoredEffect(
() => {
Expand All @@ -97,7 +126,7 @@ export const Autosave: React.FC<Props> = ({ id, collection, global: globalDoc })
let startTimestamp = undefined
let endTimestamp = undefined

const autosave = () => {
const autosave = async () => {
if (modified) {
startTimestamp = new Date().getTime()

Expand Down Expand Up @@ -129,7 +158,7 @@ export const Autosave: React.FC<Props> = ({ id, collection, global: globalDoc })
submitted && !valid && versionsConfig?.drafts && versionsConfig?.drafts?.validate

if (!skipSubmission) {
void fetch(url, {
await fetch(url, {
body: JSON.stringify(data),
credentials: 'include',
headers: {
Expand Down Expand Up @@ -229,7 +258,7 @@ export const Autosave: React.FC<Props> = ({ id, collection, global: globalDoc })
}
}

void autosave()
setQueue((prevQueue) => [...prevQueue, autosave])

return () => {
if (autosaveTimeout) {
Expand Down

0 comments on commit b9859e9

Please sign in to comment.