Skip to content

feat(core): useSyncTask #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Apr 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions apps/frontend/src/composables/useWebsocketV2.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { WsEventToServer, WsMessageToClient } from '@tg-search/server'

import { useWebSocket } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { watch } from 'vue'

import { WS_API_BASE } from '../constants'
import { useSessionStore } from '../store/useSessionV2'
import { useSyncTaskStore } from '../store/useSyncTask'

let wsContext: ReturnType<typeof createWebsocketV2Context>

Expand Down Expand Up @@ -66,14 +68,11 @@ export function createWebsocketV2Context(sessionId: string) {
connectionStore.getActiveSession()!.me = message.data
break

// case 'takeout:task:created':
// console.log('[WebSocket] Takeout task created', message.data)
// break

// case 'takeout:task:progress':
// console.log('[WebSocket] Takeout task progress', message.data)
// break

case 'takeout:task:progress': {
const { currentTask } = storeToRefs(useSyncTaskStore())
currentTask.value = message.data
break
}
default:
// eslint-disable-next-line no-console
console.log('[WebSocket] Unknown message')
Expand Down
6 changes: 6 additions & 0 deletions apps/frontend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { routes } from 'vue-router/auto-routes'
import App from './App.vue'
import en from './locales/en.json'
import zhCN from './locales/zh-CN.json'
import { useSessionStore } from './store/useSessionV2'

import '@unocss/reset/tailwind.css'
import './styles/main.css'
import 'uno.css'
Expand Down Expand Up @@ -36,3 +38,7 @@ app.use(VueQueryPlugin)
app.use(pinia)
app.use(autoAnimatePlugin)
app.mount('#app')

router.beforeEach(() => {
useSessionStore()
})
26 changes: 24 additions & 2 deletions apps/frontend/src/pages/v2sync.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { ref } from 'vue'
import { ref, watch } from 'vue'
import { toast } from 'vue-sonner'
import { useChats } from '../store/useChats'
import { useSessionStore } from '../store/useSessionV2'
import { useSyncTaskStore } from '../store/useSyncTask'

const selectedChats = ref<string[]>([])

Expand All @@ -14,13 +15,34 @@ const { isLoggedIn } = storeToRefs(sessionStore)
const chatsStore = useChats()
const { chats } = storeToRefs(chatsStore)

// const currentTask = ref<Task<'takeout'> | null>(null)
const loadingToast = ref<string | number>()

function handleSync() {
const wsContext = getWsContext()
wsContext.sendEvent('takeout:run', {
chatIds: selectedChats.value,
})
toast.success('同步开始')

loadingToast.value = toast.loading('开始同步...')
}

const { currentTask, currentTaskProgress } = storeToRefs(useSyncTaskStore())
watch(currentTaskProgress, (progress) => {
toast.dismiss(loadingToast?.value)

if (progress === 100) {
toast.dismiss(loadingToast.value)
toast.success('同步完成')
}
else if (progress < 0 && currentTask.value?.lastError) {
toast.dismiss(loadingToast.value)
toast.error(currentTask.value.lastError)
}
else {
loadingToast.value = toast.loading(`同步中... ${progress}%`)
}
})
</script>

<template>
Expand Down
16 changes: 16 additions & 0 deletions apps/frontend/src/store/useSyncTask.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { CoreTask } from '@tg-search/core'

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'

export const useSyncTaskStore = defineStore('sync-task', () => {
const currentTask = ref<CoreTask<'takeout'>>()
const currentTaskProgress = computed(() => {
if (!currentTask.value)
return 0

return currentTask.value.progress
})

return { currentTask, currentTaskProgress }
})
1 change: 1 addition & 0 deletions packages/core/src/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export type * from './event-handler'
export { createCoreInstance, destoryCoreInstance } from './instance'
export type * from './instance'
export type * from './services'
export type * from './utils/task'
4 changes: 2 additions & 2 deletions packages/core/src/v2/services/takeout.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { TelegramMessageType } from '../../types'
import type { CoreContext } from '../context'
import type { PromiseResult } from '../utils/result'
import type { Task } from '../utils/task'
import type { CoreTask } from '../utils/task'

import { useLogger } from '@tg-search/common'
import bigInt from 'big-integer'
Expand All @@ -23,7 +23,7 @@ export interface TakeoutEventToCore {
}

export interface TakeoutEventFromCore {
'takeout:task:progress': (data: Task<'takeout'>) => void
'takeout:task:progress': (data: CoreTask<'takeout'>) => void
}

export type TakeoutEvent = TakeoutEventFromCore & TakeoutEventToCore
Expand Down
20 changes: 10 additions & 10 deletions packages/core/src/v2/utils/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import type { TakeoutTaskMetadata } from '../services/takeout'

import defu from 'defu'

type TaskType = 'takeout' | 'getMessage' | 'embed'
type CoreTaskType = 'takeout' | 'getMessage' | 'embed'

interface Tasks {
interface CoreTasks {
takeout: TakeoutTaskMetadata
getMessage: undefined
embed: undefined
}

export interface Task<T extends TaskType> {
export interface CoreTask<T extends CoreTaskType> {
taskId: string
type: T
progress: number
lastMessage?: string
lastError?: string
metadata: Tasks[T]
metadata: CoreTasks[T]
createdAt: Date
updatedAt: Date
}

function createTask<T extends TaskType>(type: T, metadata: Tasks[T]): Task<T> {
function createTask<T extends CoreTaskType>(type: T, metadata: CoreTasks[T]): CoreTask<T> {
return {
taskId: crypto.randomUUID(),
type,
Expand All @@ -32,11 +32,11 @@ function createTask<T extends TaskType>(type: T, metadata: Tasks[T]): Task<T> {
}
}

export function useTasks<T extends TaskType>(type: T) {
const tasks = new Map<string, Task<T>>()
export function useTasks<T extends CoreTaskType>(type: T) {
const tasks = new Map<string, CoreTask<T>>()

return {
createTask: (data: Tasks[T]) => {
createTask: (data: CoreTasks[T]) => {
const task = createTask(type, data)
tasks.set(task.taskId, task)
return task
Expand All @@ -47,13 +47,13 @@ export function useTasks<T extends TaskType>(type: T) {
getTask: (taskId: string) => {
return tasks.get(taskId)
},
updateTask: (taskId: string, partialTask: Partial<Task<T>>) => {
updateTask: (taskId: string, partialTask: Partial<CoreTask<T>>) => {
const task = tasks.get(taskId)
if (!task) {
throw new Error(`Task ${taskId} not found`)
}

const updatedTask = defu<Task<T>, Partial<Task<T>>[]>({}, partialTask, task, {
const updatedTask = defu<CoreTask<T>, Partial<CoreTask<T>>[]>({}, partialTask, task, {
updatedAt: new Date(),
})

Expand Down