fix: 功能缺陷修复 — ImSDK login await WebSocket、fetchHistory 支持 GROUP、License 改用 apiRequest、LogQueue 重试上限
这个提交包含在:
父节点
a0c54ae191
当前提交
611f2ba95d
@ -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<void> {
|
||||
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<void>(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
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ export const ImSDK = {
|
||||
_syncHistoryForAllConversations().catch(() => {})
|
||||
},
|
||||
})
|
||||
void client.connect()
|
||||
await client.connect()
|
||||
},
|
||||
|
||||
async reconnect(): Promise<void> {
|
||||
@ -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<ImMessage[]> {
|
||||
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,
|
||||
|
||||
@ -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<void> {
|
||||
}
|
||||
|
||||
async function _post<T>(url: string, body: unknown): Promise<T> {
|
||||
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<T>(url, { method: 'POST', body })
|
||||
}
|
||||
|
||||
@ -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<typeof setInterval> | 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])
|
||||
}
|
||||
// 超过重试次数,丢弃该批次
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户