mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
fix(analytics): retry daily activity after failed posts
This commit is contained in:
1 parent
43e6ffdb81
commit
651c7f936f
2 files changed
+87
-5
No files matched your search
@@ -0,0 +1,79 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { AnalyticsService } from './analytics'
|
||||
|
||||
const APP_KEY = 'app-US-test'
|
||||
|
||||
function createTempSystemDir(): string {
|
||||
return mkdtempSync(join(tmpdir(), 'chatlab-analytics-'))
|
||||
}
|
||||
|
||||
function readAnalyticsData(systemDir: string): {
|
||||
firstReportDate?: string | null
|
||||
lastReportDate?: string | null
|
||||
} {
|
||||
return JSON.parse(readFileSync(join(systemDir, 'analytics.json'), 'utf-8'))
|
||||
}
|
||||
|
||||
test('trackDailyActive does not mark the day as reported when fetch rejects', async () => {
|
||||
const systemDir = createTempSystemDir()
|
||||
const originalFetch = globalThis.fetch
|
||||
const originalConsoleError = console.error
|
||||
globalThis.fetch = (() => Promise.reject(new Error('offline'))) as typeof fetch
|
||||
console.error = () => {}
|
||||
|
||||
try {
|
||||
await new AnalyticsService(systemDir, APP_KEY, '1.0.0').trackDailyActive()
|
||||
|
||||
assert.equal(existsSync(join(systemDir, 'analytics.json')), false)
|
||||
} finally {
|
||||
console.error = originalConsoleError
|
||||
globalThis.fetch = originalFetch
|
||||
rmSync(systemDir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
test('trackDailyActive does not mark the day as reported when Aptabase returns non-OK', async () => {
|
||||
const systemDir = createTempSystemDir()
|
||||
const originalFetch = globalThis.fetch
|
||||
globalThis.fetch = (() => Promise.resolve(new Response(null, { status: 500 }))) as typeof fetch
|
||||
|
||||
try {
|
||||
await new AnalyticsService(systemDir, APP_KEY, '1.0.0').trackDailyActive()
|
||||
|
||||
assert.equal(existsSync(join(systemDir, 'analytics.json')), false)
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch
|
||||
rmSync(systemDir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
test('trackDailyActive marks the day as reported after a successful post', async () => {
|
||||
const systemDir = createTempSystemDir()
|
||||
const originalFetch = globalThis.fetch
|
||||
const requests: Array<{ url: string; init?: RequestInit }> = []
|
||||
globalThis.fetch = ((input: RequestInfo | URL, init?: RequestInit) => {
|
||||
requests.push({ url: String(input), init })
|
||||
return Promise.resolve(new Response(null, { status: 204 }))
|
||||
}) as typeof fetch
|
||||
|
||||
try {
|
||||
await new AnalyticsService(systemDir, APP_KEY, '1.0.0').trackDailyActive({ platform: 'cli-web' })
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
assert.equal(requests.length, 1)
|
||||
assert.equal(requests[0].url, 'https://us.aptabase.com/api/v0/event')
|
||||
assert.equal(JSON.parse(String(requests[0].init?.body)).eventName, 'app_active_new')
|
||||
assert.deepEqual(readAnalyticsData(systemDir), {
|
||||
enabled: true,
|
||||
firstReportDate: today,
|
||||
lastReportDate: today,
|
||||
})
|
||||
} finally {
|
||||
globalThis.fetch = originalFetch
|
||||
rmSync(systemDir, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
@@ -62,11 +62,11 @@ export class AnalyticsService {
|
||||
this.save(data)
|
||||
}
|
||||
|
||||
async track(eventName: string, props?: Record<string, string | number>): Promise<void> {
|
||||
if (!this.endpoint) return
|
||||
if (!this.getEnabled()) return
|
||||
async track(eventName: string, props?: Record<string, string | number>): Promise<boolean> {
|
||||
if (!this.endpoint) return false
|
||||
if (!this.getEnabled()) return false
|
||||
try {
|
||||
await fetch(this.endpoint, {
|
||||
const resp = await fetch(this.endpoint, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'App-Key': this.appKey },
|
||||
body: JSON.stringify({
|
||||
@@ -86,8 +86,10 @@ export class AnalyticsService {
|
||||
props,
|
||||
}),
|
||||
})
|
||||
return resp.ok
|
||||
} catch (e) {
|
||||
console.error(`[Analytics] Failed to track ${eventName}:`, e)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +104,8 @@ export class AnalyticsService {
|
||||
if (isNew) this.save(data)
|
||||
return
|
||||
}
|
||||
await this.track(isNew ? 'app_active_new' : 'app_active', props)
|
||||
const tracked = await this.track(isNew ? 'app_active_new' : 'app_active', props)
|
||||
if (!tracked) return
|
||||
data.lastReportDate = today
|
||||
this.save(data)
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user