Run bank sync in background to avoid gateway timeouts
sync-now and sync-all now return 202 Accepted immediately and dispatch work to a background task. The frontend uses the existing SignalR BankSyncComplete notification to stop the spinner and display results. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,10 +47,10 @@ export const bankSyncApi = {
|
||||
api.put<LinkedAccountInfo>(`/bank-sync/linked-accounts/${linkedAccountId}`, data),
|
||||
|
||||
syncNow: (connectionId: string) =>
|
||||
api.post<SyncResult>(`/bank-sync/connections/${connectionId}/sync-now`),
|
||||
api.post(`/bank-sync/connections/${connectionId}/sync-now`),
|
||||
|
||||
syncAll: () =>
|
||||
api.post<SyncResult>('/bank-sync/sync-all'),
|
||||
api.post('/bank-sync/sync-all'),
|
||||
|
||||
getSyncLogs: (connectionId?: string, limit = 50) =>
|
||||
api.get<SyncLogEntry[]>('/bank-sync/sync-logs', {
|
||||
|
||||
@@ -514,12 +514,13 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { ref, reactive, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useNotifications } from '@/composables/useNotifications'
|
||||
import { bankSyncApi } from '@/services/bankSync'
|
||||
import { accountsApi } from '@/services/accounts'
|
||||
import { aiCategorizationApi } from '@/services/aiCategorization'
|
||||
import type { SyncConnection, LinkedAccountInfo, Account, SyncLogEntry, PlaidCredentials, AiCategorizationSettings, OllamaConnectionTestResult } from '@/types'
|
||||
import type { SyncConnection, LinkedAccountInfo, Account, SyncLogEntry, PlaidCredentials, AiCategorizationSettings, OllamaConnectionTestResult, BankSyncNotification } from '@/types'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
@@ -801,18 +802,27 @@ async function toggleConnection(conn: SyncConnection) {
|
||||
async function syncNow(conn: SyncConnection) {
|
||||
syncingConnections[conn.id] = true
|
||||
try {
|
||||
const { data } = await bankSyncApi.syncNow(conn.id)
|
||||
syncResultMessage.value = `Synced ${conn.institutionName}: ${data.transactionsImported} imported, ${data.transactionsSkipped} skipped`
|
||||
showSyncResult.value = true
|
||||
await loadConnections()
|
||||
await bankSyncApi.syncNow(conn.id)
|
||||
} catch (err: any) {
|
||||
syncingConnections[conn.id] = false
|
||||
errorMessage.value = err.response?.data?.error || 'Sync failed'
|
||||
showError.value = true
|
||||
} finally {
|
||||
syncingConnections[conn.id] = false
|
||||
}
|
||||
}
|
||||
|
||||
// Handle sync results via SignalR notification
|
||||
const { notifications } = useNotifications()
|
||||
watch(notifications, (notifs) => {
|
||||
const latest = notifs[0]
|
||||
if (latest && !latest.read && latest.type === 'BankSyncComplete') {
|
||||
const data = latest.data as BankSyncNotification
|
||||
syncingConnections[data.connectionId] = false
|
||||
syncResultMessage.value = `Synced ${data.institutionName}: ${data.transactionsImported} imported, ${data.transactionsSkipped} skipped`
|
||||
showSyncResult.value = true
|
||||
loadConnections()
|
||||
}
|
||||
})
|
||||
|
||||
function confirmDeleteConnection(conn: SyncConnection) {
|
||||
deleteTarget.value = conn
|
||||
showDeleteDialog.value = true
|
||||
|
||||
Reference in New Issue
Block a user