feat: update session management functions and improve partition handling
Desktop Client Build / Resolve Build Metadata (push) Successful in 31s
Frontend CI / Frontend (push) Successful in 2m58s
Backend CI / Backend (push) Successful in 18m2s
Desktop Client Build / Build Desktop Client (push) Successful in 24m49s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 38s
Desktop Client Build / Resolve Build Metadata (push) Successful in 31s
Frontend CI / Frontend (push) Successful in 2m58s
Backend CI / Backend (push) Successful in 18m2s
Desktop Client Build / Build Desktop Client (push) Successful in 24m49s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 38s
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@geo/desktop-client",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"private": true,
|
||||
"description": "省心推客户端 — 连接和管理您的媒体账号,轻松发布和监控内容表现。",
|
||||
"author": {
|
||||
|
||||
@@ -9,8 +9,8 @@ const probeAIAccountSession = vi.fn()
|
||||
const probePublishAccountSession = vi.fn()
|
||||
const silentRefreshAIAccountSession = vi.fn()
|
||||
const silentRefreshPublishAccountSession = vi.fn()
|
||||
const getSessionHandle = vi.fn()
|
||||
const getPersistedPartition = vi.fn()
|
||||
const createSessionHandleForPartition = vi.fn()
|
||||
const resolveStoredSessionPartition = vi.fn()
|
||||
const emitRuntimeInvalidated = vi.fn()
|
||||
|
||||
vi.mock('electron/main', () => ({
|
||||
@@ -27,8 +27,8 @@ vi.mock('./account-binder', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('./session-registry', () => ({
|
||||
getSessionHandle,
|
||||
getPersistedPartition,
|
||||
createSessionHandleForPartition,
|
||||
resolveStoredSessionPartition,
|
||||
}))
|
||||
|
||||
vi.mock('./runtime-events', () => ({
|
||||
@@ -68,8 +68,8 @@ describe('account health challenge recheck', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetModules()
|
||||
vi.clearAllMocks()
|
||||
getSessionHandle.mockReturnValue({ partition: 'persist:test' })
|
||||
getPersistedPartition.mockReturnValue('persist:test')
|
||||
resolveStoredSessionPartition.mockReturnValue('persist:test')
|
||||
createSessionHandleForPartition.mockReturnValue({ partition: 'persist:test' })
|
||||
silentRefreshAIAccountSession.mockResolvedValue(true)
|
||||
silentRefreshPublishAccountSession.mockResolvedValue(true)
|
||||
})
|
||||
@@ -105,4 +105,23 @@ describe('account health challenge recheck', () => {
|
||||
expect(snapshot.authState).toBe('challenge_required')
|
||||
expect(snapshot.authReason).toBe('risk_control')
|
||||
})
|
||||
|
||||
it('probes restored default partitions instead of marking restarted accounts expired', async () => {
|
||||
resolveStoredSessionPartition.mockReturnValue('persist:acc-account-1')
|
||||
probeAIAccountSession.mockResolvedValueOnce(active())
|
||||
const { probeTrackedAccount } = await import('./account-health')
|
||||
|
||||
const snapshot = await probeTrackedAccount(account, {
|
||||
trigger: 'manual',
|
||||
allowSilentRefresh: true,
|
||||
force: true,
|
||||
})
|
||||
|
||||
expect(createSessionHandleForPartition).toHaveBeenCalledWith(
|
||||
'account-1',
|
||||
'persist:acc-account-1',
|
||||
)
|
||||
expect(probeAIAccountSession).toHaveBeenCalledWith(account, 'persist:acc-account-1')
|
||||
expect(snapshot.authState).toBe('active')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
type PlatformFailureInput,
|
||||
} from './platform-auth-adapters'
|
||||
import { emitRuntimeInvalidated } from './runtime-events'
|
||||
import { getPersistedPartition, getSessionHandle } from './session-registry'
|
||||
import { createSessionHandleForPartition, resolveStoredSessionPartition } from './session-registry'
|
||||
|
||||
const PROBE_TICK_MS = 1_000
|
||||
const STALE_AFTER_MS = 45 * 60_000
|
||||
@@ -117,15 +117,16 @@ function persistedHealthPath(): string {
|
||||
}
|
||||
|
||||
function resolvePartition(accountId: string): string {
|
||||
return (
|
||||
getSessionHandle(accountId)?.partition ??
|
||||
getPersistedPartition(accountId) ??
|
||||
`persist:acc-${accountId}`
|
||||
)
|
||||
return resolveStoredSessionPartition(accountId) ?? `persist:acc-${accountId}`
|
||||
}
|
||||
|
||||
function resolveKnownPartition(accountId: string): string | null {
|
||||
return getSessionHandle(accountId)?.partition ?? getPersistedPartition(accountId) ?? null
|
||||
const partition = resolveStoredSessionPartition(accountId)
|
||||
if (!partition) {
|
||||
return null
|
||||
}
|
||||
createSessionHandleForPartition(accountId, partition)
|
||||
return partition
|
||||
}
|
||||
|
||||
function nextInitialProbeAt(now = Date.now()): number {
|
||||
|
||||
@@ -103,8 +103,7 @@ import {
|
||||
import {
|
||||
clearSessionHandle,
|
||||
createSessionHandle,
|
||||
getPersistedPartition,
|
||||
getSessionHandle,
|
||||
hasLocalSessionPartition,
|
||||
} from './session-registry'
|
||||
import {
|
||||
cancelDesktopTask,
|
||||
@@ -345,7 +344,7 @@ function isDefinitiveAuthState(authState: string): boolean {
|
||||
}
|
||||
|
||||
function hasLocalAccountSession(accountId: string): boolean {
|
||||
return Boolean(getSessionHandle(accountId) || getPersistedPartition(accountId))
|
||||
return hasLocalSessionPartition(accountId)
|
||||
}
|
||||
|
||||
function isAccountOwnedByCurrentClient(account: DesktopAccountInfo): boolean {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { randomUUID } from 'node:crypto'
|
||||
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
|
||||
import { dirname, join } from 'node:path'
|
||||
|
||||
import type { Session } from 'electron/main'
|
||||
@@ -32,6 +32,10 @@ function persistedPartitionsPath(): string {
|
||||
return join(app.getPath('userData'), 'desktop-session-partitions.json')
|
||||
}
|
||||
|
||||
function partitionsRootPath(): string {
|
||||
return join(app.getPath('userData'), 'Partitions')
|
||||
}
|
||||
|
||||
function readPersistedPartitions(): Record<string, string> {
|
||||
if (persistedPartitionsCache) {
|
||||
return persistedPartitionsCache
|
||||
@@ -111,6 +115,20 @@ function partitionFor(accountId: string): string {
|
||||
return `persist:acc-${accountId}`
|
||||
}
|
||||
|
||||
function partitionDirectoryName(partition: string): string | null {
|
||||
if (!partition.startsWith('persist:')) {
|
||||
return null
|
||||
}
|
||||
|
||||
const name = partition.slice('persist:'.length)
|
||||
return name ? name : null
|
||||
}
|
||||
|
||||
function hasPersistedPartitionDirectory(partition: string): boolean {
|
||||
const name = partitionDirectoryName(partition)
|
||||
return Boolean(name && existsSync(join(partitionsRootPath(), name)))
|
||||
}
|
||||
|
||||
function pendingPartitionFor(seed: string): string {
|
||||
return `persist:pending-${seed}-${randomUUID()}`
|
||||
}
|
||||
@@ -159,6 +177,29 @@ export function createSessionHandle(accountId?: string): SessionHandle {
|
||||
return handle
|
||||
}
|
||||
|
||||
export function hasLocalSessionPartition(accountId: string): boolean {
|
||||
return Boolean(
|
||||
registry.has(accountId) ||
|
||||
persistedPartitionFor(accountId) ||
|
||||
hasPersistedPartitionDirectory(partitionFor(accountId)),
|
||||
)
|
||||
}
|
||||
|
||||
export function resolveStoredSessionPartition(accountId: string): string | null {
|
||||
const active = registry.get(accountId)
|
||||
if (active) {
|
||||
return active.partition
|
||||
}
|
||||
|
||||
const persisted = persistedPartitionFor(accountId)
|
||||
if (persisted) {
|
||||
return persisted
|
||||
}
|
||||
|
||||
const defaultPartition = partitionFor(accountId)
|
||||
return hasPersistedPartitionDirectory(defaultPartition) ? defaultPartition : null
|
||||
}
|
||||
|
||||
export function createSessionHandleForPartition(
|
||||
accountId: string,
|
||||
partition: string,
|
||||
|
||||
@@ -385,7 +385,8 @@ async function cleanDesktopStorageOnce(): Promise<DesktopStorageCleanupResult> {
|
||||
|
||||
for (const [partition, accountId] of persistedPartitions) {
|
||||
const root = partitionPath(partition)
|
||||
if (root && before.entries.some((entry) => entry.partition === partition)) {
|
||||
const footprint = root ? await directoryFootprint(root) : { bytes: 0, lastModifiedAt: null }
|
||||
if (footprint.bytes > 0 || footprint.lastModifiedAt) {
|
||||
continue
|
||||
}
|
||||
forgetPersistedSessionPartition(accountId, partition)
|
||||
|
||||
Reference in New Issue
Block a user