summaryrefslogtreecommitdiff
path: root/hooks/use-sync-status.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:34:39 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:34:39 +0000
commitc2aa314651219686f78700e87135485a8be91264 (patch)
tree0b7e240d2432863754cfed47ff4020d7edc0c5be /hooks/use-sync-status.ts
parentb7f5af1f4b6691052bb3e77968a478ff27696095 (diff)
(대표님) 커스텀 훅, ATOM 상태관리, 타입 정의 커밋
Diffstat (limited to 'hooks/use-sync-status.ts')
-rw-r--r--hooks/use-sync-status.ts189
1 files changed, 189 insertions, 0 deletions
diff --git a/hooks/use-sync-status.ts b/hooks/use-sync-status.ts
new file mode 100644
index 00000000..07cb3432
--- /dev/null
+++ b/hooks/use-sync-status.ts
@@ -0,0 +1,189 @@
+// hooks/use-sync-status.ts (수정된 버전)
+import useSWR from 'swr'
+import useSWRMutation from 'swr/mutation'
+import { mutate } from 'swr'
+
+// 단순한 fetcher 함수들
+const fetcher = async (url: string) => {
+ const response = await fetch(url)
+ if (!response.ok) {
+ const error = new Error(`HTTP ${response.status}`)
+ ;(error as any).status = response.status
+ throw error
+ }
+ return response.json()
+}
+
+// 동기화 상태 조회
+export function useSyncStatus(contractId: number, targetSystem: string = 'SHI') {
+ const key = contractId
+ ? `/api/sync/status?contractId=${contractId}&targetSystem=${targetSystem}`
+ : null
+
+ const { data, error, isLoading } = useSWR(
+ key,
+ fetcher,
+ {
+ refreshInterval: 30000, // 30초마다 갱신
+ revalidateOnFocus: true,
+ revalidateOnReconnect: true,
+ shouldRetryOnError: false, // 에러시 자동 재시도 비활성화
+ dedupingInterval: 5000, // 5초 내 중복 요청 방지
+ }
+ )
+
+ const refetch = () => {
+ if (key) {
+ mutate(key)
+ }
+ }
+
+ return {
+ syncStatus: data,
+ isLoading,
+ error,
+ refetch
+ }
+}
+
+// 동기화 배치 목록 조회
+export function useSyncBatches(contractId: number, targetSystem: string = 'SHI') {
+ const key = contractId
+ ? `/api/sync/batches?contractId=${contractId}&targetSystem=${targetSystem}`
+ : null
+
+ const { data, error, isLoading } = useSWR(
+ key,
+ fetcher,
+ {
+ revalidateOnFocus: false,
+ shouldRetryOnError: false,
+ }
+ )
+
+ return {
+ syncBatches: data,
+ isLoading,
+ error
+ }
+}
+
+// 동기화 설정 조회
+export function useSyncConfig(contractId: number, targetSystem: string = 'SHI') {
+ const key = contractId
+ ? `/api/sync/config?contractId=${contractId}&targetSystem=${targetSystem}`
+ : null
+
+ const { data, error, isLoading } = useSWR(
+ key,
+ fetcher,
+ {
+ revalidateOnFocus: false,
+ shouldRetryOnError: false,
+ }
+ )
+
+ return {
+ syncConfig: data,
+ isLoading,
+ error
+ }
+}
+
+// 동기화 트리거 (뮤테이션)
+export function useTriggerSync() {
+ const { trigger, isMutating, error } = useSWRMutation(
+ '/api/sync/trigger',
+ async (url: string, { arg }: { arg: { contractId: number; targetSystem?: string } }) => {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(arg)
+ })
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}))
+ const error = new Error(errorData.message || `HTTP ${response.status}`)
+ ;(error as any).status = response.status
+ throw error
+ }
+
+ return response.json()
+ },
+ {
+ onSuccess: (data, key, config) => {
+ // 관련 캐시 무효화
+ const { contractId, targetSystem = 'SHI' } = config.arg
+ const statusKey = `/api/sync/status?contractId=${contractId}&targetSystem=${targetSystem}`
+ const batchesKey = `/api/sync/batches?contractId=${contractId}&targetSystem=${targetSystem}`
+
+ mutate(statusKey)
+ mutate(batchesKey)
+ },
+ onError: (error) => {
+ console.error('Sync trigger failed:', error)
+ }
+ }
+ )
+
+ return {
+ triggerSync: trigger,
+ isLoading: isMutating,
+ error
+ }
+}
+
+// 동기화 설정 업데이트 (뮤테이션)
+export function useUpdateSyncConfig() {
+ const { trigger, isMutating, error } = useSWRMutation(
+ '/api/sync/config',
+ async (url: string, { arg }: { arg: any }) => {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(arg)
+ })
+
+ if (!response.ok) {
+ const errorData = await response.json().catch(() => ({}))
+ const error = new Error(errorData.message || `HTTP ${response.status}`)
+ ;(error as any).status = response.status
+ throw error
+ }
+
+ return response.json()
+ },
+ {
+ onSuccess: (data, key, config) => {
+ // 설정 캐시 무효화
+ const { contractId, targetSystem } = config.arg
+ const configKey = `/api/sync/config?contractId=${contractId}&targetSystem=${targetSystem}`
+ mutate(configKey)
+ },
+ }
+ )
+
+ return {
+ updateConfig: trigger,
+ isLoading: isMutating,
+ error
+ }
+}
+
+// 실시간 동기화 상태 훅 (높은 갱신 빈도)
+export function useRealtimeSyncStatus(contractId: number, targetSystem: string = 'SHI') {
+ const key = contractId
+ ? `/api/sync/status?contractId=${contractId}&targetSystem=${targetSystem}&realtime=true`
+ : null
+
+ return useSWR(
+ key,
+ fetcher,
+ {
+ refreshInterval: 5000, // 5초마다 갱신 (실시간)
+ revalidateOnFocus: true,
+ revalidateOnReconnect: true,
+ shouldRetryOnError: false,
+ }
+ )
+} \ No newline at end of file