-
Notifications
You must be signed in to change notification settings - Fork 731
Expand file tree
/
Copy pathexportActivity.ts
More file actions
81 lines (72 loc) · 2.62 KB
/
Copy pathexportActivity.ts
File metadata and controls
81 lines (72 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/**
* Export activity: Execute PCC COPY INTO + write metadata.
*
* Full daily export of leaf projects from ANALYTICS.SILVER_DIM.PROJECTS joined
* with PROJECT_SPINE to produce one row per (leaf, hierarchy_level) pair.
* No incremental logic — at ~1,538 leaf rows, a full daily export is simpler
* and more reliable than incremental (a parent name change would require
* re-exporting all descendants).
*/
import { WRITE_DB_CONFIG, getDbConnection } from '@crowd/database'
import { getServiceChildLogger } from '@crowd/logging'
import { MetadataStore, SnowflakeExporter, buildS3FilenamePrefix } from '@crowd/snowflake'
const log = getServiceChildLogger('exportActivity')
const PLATFORM = 'pcc'
const SOURCE_NAME = 'project-hierarchy'
function buildSourceQuery(): string {
return `
SELECT
p.project_id,
p.name,
p.description,
p.project_logo,
p.project_status,
p.project_admin_category,
ps.mapped_project_id,
ps.mapped_project_name,
ps.mapped_project_slug,
ps.hierarchy_level,
s.segment_id
FROM ANALYTICS.SILVER_DIM.PROJECTS p
LEFT JOIN ANALYTICS.SILVER_DIM.PROJECT_SPINE ps ON ps.base_project_id = p.project_id
LEFT JOIN ANALYTICS.SILVER_DIM.ACTIVE_SEGMENTS s
ON s.source_id = p.project_id
AND s.project_type = 'subproject'
WHERE p.project_id NOT IN (
SELECT DISTINCT parent_id
FROM ANALYTICS.SILVER_DIM.PROJECTS
WHERE parent_id IS NOT NULL
)
ORDER BY p.name, ps.hierarchy_level ASC
`
}
export async function executeExport(): Promise<void> {
log.info({ platform: PLATFORM, sourceName: SOURCE_NAME }, 'Starting PCC export')
const exporter = new SnowflakeExporter()
const db = await getDbConnection(WRITE_DB_CONFIG())
try {
const metadataStore = new MetadataStore(db)
const sourceQuery = buildSourceQuery()
const s3FilenamePrefix = buildS3FilenamePrefix(PLATFORM, SOURCE_NAME)
const exportStartedAt = new Date()
const onBatchComplete = async (s3Path: string, totalRows: number, totalBytes: number) => {
await metadataStore.insertExportJob(
PLATFORM,
SOURCE_NAME,
s3Path,
totalRows,
totalBytes,
exportStartedAt,
)
}
await exporter.executeBatchedCopyInto(sourceQuery, s3FilenamePrefix, onBatchComplete)
log.info({ platform: PLATFORM, sourceName: SOURCE_NAME }, 'PCC export completed')
} catch (err) {
log.error({ platform: PLATFORM, sourceName: SOURCE_NAME, err }, 'PCC export failed')
throw err
} finally {
await exporter
.destroy()
.catch((err) => log.warn({ err }, 'Failed to close Snowflake connection'))
}
}