diff --git a/packages/im/src/ImClient.ts b/packages/im/src/ImClient.ts index 5dbe517..379be8e 100644 --- a/packages/im/src/ImClient.ts +++ b/packages/im/src/ImClient.ts @@ -18,6 +18,7 @@ export class ImClient { private activeWsUrl: string | null = null private activeToken: string | null = null private activeAppKey: string | null = null + private connectedResolvers: Array<() => void> = [] constructor( private readonly wsUrl?: string, @@ -25,7 +26,7 @@ export class ImClient { private readonly appKey?: string, ) {} - async connect() { + async connect(): Promise { this.shouldReconnect = true this.activeWsUrl = this.wsUrl ?? getConfig().imWsUrl this.activeToken = this.token ?? null @@ -42,6 +43,10 @@ export class ImClient { return } this.openSocket() + // 等待 STOMP CONNECTED 帧 + await new Promise(resolve => { + this.connectedResolvers.push(resolve) + }) } sendMessage( @@ -222,6 +227,8 @@ export class ImClient { this.subscribe(`/topic/group/${groupId}`, `group-${groupId}`) }) this.sendSync() + this.connectedResolvers.forEach(resolve => resolve()) + this.connectedResolvers = [] this.listeners.forEach(listener => listener.onConnected?.()) return } diff --git a/packages/im/src/ImSDK.ts b/packages/im/src/ImSDK.ts index a761e93..5e36fac 100644 --- a/packages/im/src/ImSDK.ts +++ b/packages/im/src/ImSDK.ts @@ -320,7 +320,7 @@ export const ImSDK = { _syncHistoryForAllConversations().catch(() => {}) }, }) - void client.connect() + await client.connect() }, async reconnect(): Promise { @@ -328,17 +328,18 @@ export const ImSDK = { const token = await _getToken() if (!token) throw new Error('[ImSDK] No active session — call login() first.') client = new ImClient(config.imWsUrl, token, config.appKey) - void client.connect() + await client.connect() }, async fetchHistory( toId: string, page = 0, size = 20, + chatType: ChatType = 'SINGLE', ): Promise { const config = getConfig() if (ImDatabase.isInitialized() && page === 0 && _currentUserId) { - const local = await ImDatabase.getMessages(config.appKey, toId, 'SINGLE', _currentUserId, size) + const local = await ImDatabase.getMessages(config.appKey, toId, chatType, _currentUserId, size) if (local.length > 0) { return local.map(model => ({ id: model.serverId, diff --git a/packages/license/src/license.ts b/packages/license/src/license.ts index 69dffab..7d54a89 100644 --- a/packages/license/src/license.ts +++ b/packages/license/src/license.ts @@ -1,5 +1,5 @@ import { Platform } from 'react-native' -import { getDeviceId as getCommonDeviceId, getDeviceInfo, awaitInitialization, getConfig, getUserId } from '@xuqm/rn-common' +import { getDeviceId as getCommonDeviceId, getDeviceInfo, awaitInitialization, getConfig, getUserId, apiRequest } from '@xuqm/rn-common' import * as store from './store' import type { LicenseResult, LicenseStatus, LicenseUserInfo, RegisterRequest, RegisterResponse, VerifyRequest, VerifyResponse } from './models' @@ -101,15 +101,5 @@ async function _persistStatus(status: string): Promise { } async function _post(url: string, body: unknown): Promise { - const res = await fetch(url, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(body), - }) - if (!res.ok) { - const err = await res.json().catch(() => ({ message: res.statusText })) as { message?: string } - throw new Error(err.message ?? `HTTP ${res.status}`) - } - const json = await res.json() as { data?: T } - return (json.data ?? json) as T + return apiRequest(url, { method: 'POST', body }) } diff --git a/packages/log/src/queue/LogQueue.ts b/packages/log/src/queue/LogQueue.ts index 6d898cb..75191be 100644 --- a/packages/log/src/queue/LogQueue.ts +++ b/packages/log/src/queue/LogQueue.ts @@ -5,9 +5,11 @@ const QUEUE_KEY = '@xuqm_log:queue' const BATCH_SIZE = 30 const FLUSH_INTERVAL_MS = 10_000 // 10 seconds const MAX_QUEUE_SIZE = 500 +const MAX_RETRY = 3 export class LogQueue { private flushTimer: ReturnType | null = null + private retryCount = 0 constructor(private cfg: { logApiUrl: string; appKey: string }) { this.flushTimer = setInterval(() => { @@ -35,10 +37,14 @@ export class LogQueue { try { if (issues.length > 0) await this._post('/log/v1/issues/batch', issues) if (events.length > 0) await this._post('/log/v1/events/batch', events) + this.retryCount = 0 } catch { - // On failure, push batch back to front of queue (retry once on next flush) - const current = await this._read() - await this._write([...batch, ...current]) + this.retryCount++ + if (this.retryCount < MAX_RETRY) { + const current = await this._read() + await this._write([...batch, ...current]) + } + // 超过重试次数,丢弃该批次 } }