-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathtestContext.ts
More file actions
113 lines (102 loc) · 3.27 KB
/
Copy pathtestContext.ts
File metadata and controls
113 lines (102 loc) · 3.27 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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import { randomUUID } from 'node:crypto'
import {
type CommonLogger,
type ErrorReporter,
globalLogger,
type TransactionObservabilityManager,
} from '@lokalise/node-core'
import type { MessageMetricsManager } from '@message-queue-toolkit/core'
import { Admin } from '@platformatic/kafka'
import {
type AwilixContainer,
asFunction,
createContainer,
Lifetime,
type NameAndRegistrationPair,
} from 'awilix'
import { AwilixManager } from 'awilix-manager'
import type { KafkaConfig } from '../../lib/index.ts'
const SINGLETON_CONFIG = { lifetime: Lifetime.SINGLETON }
type DiConfig = NameAndRegistrationPair<Dependencies>
export type TestContext = AwilixContainer<Dependencies>
type Dependencies = {
awilixManager: AwilixManager
kafkaConfig: KafkaConfig
kafkaAdmin: Admin
errorReporter: ErrorReporter
logger: CommonLogger
transactionObservabilityManager: TransactionObservabilityManager
messageMetricsManager: MessageMetricsManager<object>
}
export const createTestContext = async (): Promise<TestContext> => {
const diContainer = createContainer<Dependencies>({
injectionMode: 'PROXY',
})
const awilixManager = new AwilixManager({
diContainer,
asyncDispose: true,
asyncInit: true,
eagerInject: true,
})
diContainer.register(resolveDIConfig(awilixManager))
await awilixManager.executeInit()
return diContainer
}
export const getKafkaConfig = (): KafkaConfig => ({
bootstrapBrokers: ['localhost:9092'],
clientId: randomUUID(),
})
/**
* Deletes only the topics that currently exist.
*
* Workaround for a regression in @platformatic/kafka >= 2.3.0 where Admin#deleteTopics
* leaves a stale entry in its internal deduplication cache when the operation errors
* (e.g. deleting a non-existent topic). Reusing the same Admin instance afterwards causes
* subsequent deleteTopics calls for the same topics to hang. Filtering to existing topics
* avoids triggering that error path.
*/
export const deleteExistingTopics = async (kafkaAdmin: Admin, topics: string[]): Promise<void> => {
const existingTopics = await kafkaAdmin.listTopics()
const topicsToDelete = topics.filter((topic) => existingTopics.includes(topic))
if (topicsToDelete.length === 0) return
await kafkaAdmin.deleteTopics({ topics: topicsToDelete })
}
const resolveDIConfig = (awilixManager: AwilixManager): DiConfig => ({
awilixManager: asFunction(() => awilixManager, SINGLETON_CONFIG),
kafkaConfig: asFunction(getKafkaConfig, SINGLETON_CONFIG),
kafkaAdmin: asFunction(
({ kafkaConfig }) =>
new Admin({
clientId: randomUUID(),
bootstrapBrokers: kafkaConfig.bootstrapBrokers,
}),
{
lifetime: Lifetime.SINGLETON,
asyncDispose: 'close',
},
),
logger: asFunction(() => globalLogger, SINGLETON_CONFIG),
errorReporter: asFunction(
() =>
({
report: () => {},
}) satisfies ErrorReporter,
SINGLETON_CONFIG,
),
transactionObservabilityManager: asFunction(
() =>
({
start: vi.fn(),
stop: vi.fn(),
startWithGroup: vi.fn(),
addCustomAttributes: vi.fn(),
}) satisfies TransactionObservabilityManager,
SINGLETON_CONFIG,
),
messageMetricsManager: asFunction(
() => ({
registerProcessedMessage: () => undefined,
}),
SINGLETON_CONFIG,
),
})