MCPcopy Create free account
hub / github.com/Openpanel-dev/openpanel / importJob

Function importJob

apps/worker/src/jobs/import.ts:71–378  ·  view source on GitHub ↗
(job: Job<ImportQueuePayload>)

Source from the content-addressed store, hash-verified

69}
70
71export async function importJob(job: Job<ImportQueuePayload>) {
72 const { importId } = job.data.payload;
73
74 const record = await db.import.findUniqueOrThrow({
75 where: { id: importId },
76 include: { project: true },
77 });
78
79 const jobLogger = logger.child({ importId, config: record.config });
80 jobLogger.info('Starting import job');
81
82 const providerInstance = createProvider(record, jobLogger);
83 const shouldGenerateSessionIds = providerInstance.shouldGenerateSessionIds();
84
85 try {
86 const isRetry = record.currentStep !== null;
87 const canResume =
88 isRetry && RESUMABLE_STEPS.includes(record.currentStep as string);
89
90 // -------------------------------------------------------
91 // STAGING PHASE: clean slate on failure, run from scratch
92 // -------------------------------------------------------
93 if (!canResume) {
94 if (isRetry) {
95 jobLogger.info(
96 'Retry detected before resumable phase — cleaning staging data'
97 );
98 await cleanupStagingData(importId);
99 }
100
101 // Phase 1: Load events into staging
102 await updateImportStatus(jobLogger, job, importId, { step: 'loading' });
103
104 const totalEvents = await providerInstance
105 .getTotalEventsCount()
106 .catch(() => -1);
107 let processedEvents = 0;
108 const eventBatch: IClickhouseEvent[] = [];
109
110 // Profiles derived inline from events (e.g. Amplitude, which has no
111 // profile export API). A bounded dedup map keeps memory flat regardless of
112 // event volume; the profiles table's ReplacingMergeTree(last_seen_at)
113 // collapses any duplicate rows that span flush boundaries to the latest
114 // activity per id.
115 const canProfileFromEvents =
116 typeof (providerInstance as AmplitudeProvider)
117 .transformEventToProfile === 'function';
118 const PROFILE_MAP_CAP = 50_000;
119 const profileMap = new Map<string, IClickhouseProfile>();
120 let processedProfiles = 0;
121
122 const flushProfiles = async () => {
123 if (profileMap.size === 0) {
124 return;
125 }
126 const values = Array.from(profileMap.values());
127 await insertProfilesBatch(values, record.projectId);
128 processedProfiles += values.length;

Callers

nothing calls this directly

Calls 15

cleanupStagingDataFunction · 0.90
updateImportStatusFunction · 0.90
insertImportBatchFunction · 0.90
insertProfilesBatchFunction · 0.90
getImportDateBoundsFunction · 0.90
moveImportsToProductionFunction · 0.90
createProviderFunction · 0.85
mergeProfileIntoFunction · 0.85

Tested by

no test coverage detected