| 79 | // ==================== WorkerImporter ==================== |
| 80 | |
| 81 | export class WorkerImporter implements DataImporter { |
| 82 | private logger: SyncLogger |
| 83 | |
| 84 | constructor(logger?: SyncLogger) { |
| 85 | this.logger = logger ?? NOOP_LOGGER |
| 86 | } |
| 87 | |
| 88 | sessionExists(sessionId: string): boolean { |
| 89 | assertDesktopDataDirCompatible(getPathProvider(), getDesktopAppVersion(app.getVersion())) |
| 90 | |
| 91 | const dbPath = path.join(worker.getDbDirectory(), `${sessionId}.db`) |
| 92 | if (!fs.existsSync(dbPath)) return false |
| 93 | try { |
| 94 | const db = new Database(dbPath, { readonly: true }) |
| 95 | const row = db |
| 96 | .prepare("SELECT COUNT(*) as cnt FROM sqlite_master WHERE type='table' AND name='message'") |
| 97 | .get() as { cnt: number } |
| 98 | db.close() |
| 99 | if (row.cnt === 0) { |
| 100 | this.logger.warn(`[Pull] DB file exists but has no message table: ${sessionId}, removing`) |
| 101 | try { |
| 102 | fs.unlinkSync(dbPath) |
| 103 | } catch { |
| 104 | /* ignore */ |
| 105 | } |
| 106 | return false |
| 107 | } |
| 108 | return true |
| 109 | } catch { |
| 110 | this.logger.warn(`[Pull] Cannot validate DB file: ${sessionId}, removing`) |
| 111 | try { |
| 112 | fs.unlinkSync(dbPath) |
| 113 | } catch { |
| 114 | /* ignore */ |
| 115 | } |
| 116 | return false |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | async importFile(tempFile: string, targetSessionId: string | undefined, externalId: string): Promise<ImportResult> { |
| 121 | if (targetSessionId && this.sessionExists(targetSessionId)) { |
| 122 | return this.incrementalImportFile(targetSessionId, tempFile) |
| 123 | } |
| 124 | return this.fullImportFile(tempFile, externalId) |
| 125 | } |
| 126 | |
| 127 | private async incrementalImportFile(sessionId: string, tempFile: string): Promise<ImportResult> { |
| 128 | this.logger.info(`[Pull] Incremental import to session ${sessionId}`) |
| 129 | const result = await worker.incrementalImport(sessionId, tempFile) |
| 130 | if (result.success) { |
| 131 | this.logger.info(`[Pull] Incremental OK: +${result.newMessageCount} messages`) |
| 132 | return { success: true, newMessageCount: result.newMessageCount, sessionId } |
| 133 | } |
| 134 | if (result.error === 'error.session_not_found' || result.error?.includes('no such table')) { |
| 135 | this.logger.warn(`[Pull] Session ${sessionId} not found or schema invalid, need full resync`) |
| 136 | return { success: false, newMessageCount: 0, sessionId, needFullResync: true } |
| 137 | } |
| 138 | this.logger.error(`[Pull] Incremental import failed: ${result.error}`) |
nothing calls this directly
no outgoing calls
no test coverage detected