Skip to content

Commit 6064394

Browse files
authored
Merge pull request #532 from aurelianware/claude/fix-portal-rollout-timeout-eTHyI
Claude/fix portal rollout timeout e t hy i
2 parents c54c1d8 + caa67e7 commit 6064394

File tree

8 files changed

+63
-85
lines changed

8 files changed

+63
-85
lines changed

src/portal/CloudHealthOffice.Portal/k8s/portal-deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ spec:
244244
apiVersion: apps/v1
245245
kind: Deployment
246246
name: portal
247-
minReplicas: 2 # Safe with Redis-backed session + token cache
247+
minReplicas: 1 # Safe with Redis-backed session + token cache
248248
maxReplicas: 5
249249
metrics:
250250
- type: Resource

src/services/claims-scrubbing-service/k8s/claims-scrubbing-service-deployment.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ data:
1212
CLEAN_CLAIMS_TOPIC: "claims.clean"
1313
FLAGGED_CLAIMS_TOPIC: "claims.flagged"
1414
REJECTED_CLAIMS_TOPIC: "claims.rejected"
15-
COSMOS_DATABASE: "CloudHealthOffice"
16-
COSMOS_RULES_CONTAINER: "ScrubRules"
17-
COSMOS_AUDIT_CONTAINER: "ScrubAudit"
15+
MONGODB_DATABASE: "CloudHealthOffice"
16+
MONGODB_RULES_COLLECTION: "ScrubRules"
17+
MONGODB_AUDIT_COLLECTION: "ScrubAudit"
1818
CLAIMS_CONTAINER: "claims-archive"
1919
PARALLEL_RULES: "true"
2020
MAX_RULE_CONCURRENCY: "10"
@@ -72,11 +72,11 @@ spec:
7272
name: kafka-secret
7373
key: saslPassword
7474
optional: true
75-
- name: COSMOS_ENDPOINT
75+
- name: MONGODB_CONNECTION_STRING
7676
valueFrom:
7777
secretKeyRef:
78-
name: cosmos-db-secret
79-
key: endpoint
78+
name: mongodb-secret
79+
key: connectionString
8080
- name: STORAGE_CONNECTION_STRING
8181
valueFrom:
8282
secretKeyRef:

src/services/claims-scrubbing-service/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@
3333
"author": "Cloud Health Office Team",
3434
"license": "Apache-2.0",
3535
"dependencies": {
36-
"@azure/cosmos": "^4.2.0",
3736
"@azure/identity": "^4.13.0",
3837
"@azure/keyvault-secrets": "^4.9.0",
3938
"@azure/storage-blob": "^12.30.0",
39+
"mongodb": "^6.12.0",
4040
"kafkajs": "^2.2.4",
4141
"uuid": "^13.0.0"
4242
},

src/services/claims-scrubbing-service/src/claims-scrubber.ts

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
* - Configurable validation rule engine
99
* - Standard and custom rule support
1010
* - Kafka integration for claim routing
11-
* - Cosmos DB for rule storage and audit
11+
* - MongoDB for rule storage and audit
1212
* - First-pass rate metrics tracking
1313
*/
1414

1515
import { Kafka, Producer, Consumer, logLevel } from 'kafkajs';
16-
import { CosmosClient, Container, Database } from '@azure/cosmos';
16+
import { MongoClient, Db, Collection } from 'mongodb';
1717
import { BlobServiceClient, ContainerClient } from '@azure/storage-blob';
1818
import { DefaultAzureCredential } from '@azure/identity';
1919
import { v4 as uuidv4 } from 'uuid';
@@ -43,10 +43,10 @@ export class ClaimsScrubberService {
4343
private kafka: Kafka | null = null;
4444
private producer: Producer | null = null;
4545
private consumer: Consumer | null = null;
46-
private cosmosClient: CosmosClient | null = null;
47-
private database: Database | null = null;
48-
private rulesContainer: Container | null = null;
49-
private auditContainer: Container | null = null;
46+
private mongoClient: MongoClient | null = null;
47+
private database: Db | null = null;
48+
private rulesCollection: Collection | null = null;
49+
private auditCollection: Collection | null = null;
5050
private blobServiceClient: BlobServiceClient | null = null;
5151
private archiveContainer: ContainerClient | null = null;
5252
private startTime: number;
@@ -104,14 +104,12 @@ export class ClaimsScrubberService {
104104
});
105105
}
106106

107-
// Initialize Cosmos DB
108-
this.cosmosClient = new CosmosClient({
109-
endpoint: this.config.cosmosDb.endpoint,
110-
aadCredentials: credential,
111-
});
112-
this.database = this.cosmosClient.database(this.config.cosmosDb.databaseName);
113-
this.rulesContainer = this.database.container(this.config.cosmosDb.rulesContainerName);
114-
this.auditContainer = this.database.container(this.config.cosmosDb.auditContainerName);
107+
// Initialize MongoDB
108+
this.mongoClient = new MongoClient(this.config.mongoDb.connectionString);
109+
await this.mongoClient.connect();
110+
this.database = this.mongoClient.db(this.config.mongoDb.databaseName);
111+
this.rulesCollection = this.database.collection(this.config.mongoDb.rulesCollectionName);
112+
this.auditCollection = this.database.collection(this.config.mongoDb.auditCollectionName);
115113

116114
// Initialize Blob Storage
117115
if (this.config.storage.connectionString) {
@@ -127,29 +125,26 @@ export class ClaimsScrubberService {
127125
this.archiveContainer = this.blobServiceClient.getContainerClient(this.config.storage.containerName);
128126
}
129127

130-
// Load custom rules from Cosmos DB
128+
// Load custom rules from MongoDB
131129
await this.loadCustomRules();
132130
}
133131

134132
/**
135-
* Load custom rules from Cosmos DB
133+
* Load custom rules from MongoDB
136134
*/
137135
private async loadCustomRules(): Promise<void> {
138-
if (!this.rulesContainer) return;
136+
if (!this.rulesCollection) return;
139137

140138
try {
141-
const query = {
142-
query: 'SELECT * FROM c WHERE c.type = @type AND c.enabled = true',
143-
parameters: [{ name: '@type', value: 'custom' }],
144-
};
145-
146-
const { resources } = await this.rulesContainer.items.query<CustomRule>(query).fetchAll();
139+
const resources = await this.rulesCollection
140+
.find<CustomRule>({ type: 'custom', enabled: true })
141+
.toArray();
147142

148143
for (const rule of resources) {
149144
this.ruleEngine.addCustomRule(rule);
150145
}
151146

152-
console.log(`Loaded ${resources.length} custom rules from Cosmos DB`);
147+
console.log(`Loaded ${resources.length} custom rules from MongoDB`);
153148
} catch (error) {
154149
console.error('Failed to load custom rules:', error);
155150
}
@@ -376,18 +371,17 @@ export class ClaimsScrubberService {
376371
}
377372

378373
/**
379-
* Audit the validation to Cosmos DB
374+
* Audit the validation to MongoDB
380375
*/
381376
private async auditValidation(
382377
claim: X12_837_Claim,
383378
result: ClaimValidationResult,
384379
correlationId: string
385380
): Promise<void> {
386-
if (!this.auditContainer) return;
381+
if (!this.auditCollection) return;
387382

388383
try {
389384
const auditRecord = {
390-
id: uuidv4(),
391385
claimId: claim.claimId,
392386
claimType: claim.claimType,
393387
patientControlNumber: claim.claimHeader.patientControlNumber,
@@ -405,11 +399,11 @@ export class ClaimsScrubberService {
405399
.map(r => r.editCode),
406400
validationTimeMs: result.totalValidationTimeMs,
407401
correlationId,
408-
timestamp: new Date().toISOString(),
409-
ttl: 90 * 24 * 60 * 60, // 90 days TTL
402+
timestamp: new Date(),
403+
expireAt: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000), // 90 days TTL
410404
};
411405

412-
await this.auditContainer.items.create(auditRecord);
406+
await this.auditCollection.insertOne(auditRecord);
413407
} catch (error) {
414408
console.error('Failed to audit claim', { claimId: claim.claimId }, error);
415409
}
@@ -419,9 +413,9 @@ export class ClaimsScrubberService {
419413
* Add a custom validation rule
420414
*/
421415
async addCustomRule(rule: CustomRule): Promise<void> {
422-
// Save to Cosmos DB
423-
if (this.rulesContainer) {
424-
await this.rulesContainer.items.create(rule);
416+
// Save to MongoDB
417+
if (this.rulesCollection) {
418+
await this.rulesCollection.insertOne(rule);
425419
}
426420

427421
// Add to in-memory rule engine
@@ -448,7 +442,7 @@ export class ClaimsScrubberService {
448442
async getHealth(): Promise<HealthStatus> {
449443
const checks: HealthStatus['checks'] = {
450444
kafka: await this.checkKafkaHealth(),
451-
cosmosDb: await this.checkCosmosDbHealth(),
445+
mongoDb: await this.checkMongoDbHealth(),
452446
storage: await this.checkStorageHealth(),
453447
ruleEngine: this.checkRuleEngineHealth(),
454448
};
@@ -515,19 +509,19 @@ export class ClaimsScrubberService {
515509
}
516510

517511
/**
518-
* Check Cosmos DB health
512+
* Check MongoDB health
519513
*/
520-
private async checkCosmosDbHealth(): Promise<ComponentHealth> {
514+
private async checkMongoDbHealth(): Promise<ComponentHealth> {
521515
const start = Date.now();
522516
try {
523517
if (!this.database) {
524518
return {
525519
status: 'unhealthy',
526520
lastCheck: new Date().toISOString(),
527-
error: 'Cosmos DB client not initialized',
521+
error: 'MongoDB client not initialized',
528522
};
529523
}
530-
await this.database.read();
524+
await this.database.command({ ping: 1 });
531525
return {
532526
status: 'healthy',
533527
latencyMs: Date.now() - start,
@@ -629,6 +623,7 @@ export class ClaimsScrubberService {
629623
async close(): Promise<void> {
630624
if (this.consumer) await this.consumer.disconnect();
631625
if (this.producer) await this.producer.disconnect();
626+
if (this.mongoClient) await this.mongoClient.close();
632627
}
633628
}
634629

src/services/claims-scrubbing-service/src/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ function getConfig(): ClaimsScrubberConfig {
4949
containerName: process.env.CLAIMS_CONTAINER || 'claims-archive',
5050
archivePathPattern: '{claimType}/{status}/{yyyy}/{MM}/{dd}',
5151
},
52-
cosmosDb: {
53-
endpoint: process.env.COSMOS_ENDPOINT || '',
54-
databaseName: process.env.COSMOS_DATABASE || 'claims-scrubbing',
55-
rulesContainerName: process.env.COSMOS_RULES_CONTAINER || 'validation-rules',
56-
auditContainerName: process.env.COSMOS_AUDIT_CONTAINER || 'validation-audit',
52+
mongoDb: {
53+
connectionString: process.env.MONGODB_CONNECTION_STRING || '',
54+
databaseName: process.env.MONGODB_DATABASE || 'CloudHealthOffice',
55+
rulesCollectionName: process.env.MONGODB_RULES_COLLECTION || 'ScrubRules',
56+
auditCollectionName: process.env.MONGODB_AUDIT_COLLECTION || 'ScrubAudit',
5757
},
5858
ruleEngine: {
5959
parallelExecution: process.env.PARALLEL_RULES === 'true',
@@ -357,11 +357,11 @@ async function start(): Promise<void> {
357357
// Initialize service (connect to Azure resources)
358358
// Skip initialization in development mode without Azure resources
359359
const config = getConfig();
360-
if (config.cosmosDb.endpoint) {
360+
if (config.mongoDb.connectionString) {
361361
await svc.initialize();
362362
console.log('Claims Scrubbing Service initialized');
363363
} else {
364-
console.log('Running in development mode (no Azure resources)');
364+
console.log('Running in development mode (no database configured)');
365365
}
366366

367367
server.listen(PORT, () => {

src/services/claims-scrubbing-service/src/types.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -652,12 +652,12 @@ export interface ClaimsScrubberConfig {
652652
/** Archive path pattern */
653653
archivePathPattern: string;
654654
};
655-
/** Cosmos DB for rule storage and audit */
656-
cosmosDb: {
657-
endpoint: string;
655+
/** MongoDB for rule storage and audit */
656+
mongoDb: {
657+
connectionString: string;
658658
databaseName: string;
659-
rulesContainerName: string;
660-
auditContainerName: string;
659+
rulesCollectionName: string;
660+
auditCollectionName: string;
661661
};
662662
/** Rule engine configuration */
663663
ruleEngine: {
@@ -770,7 +770,7 @@ export interface HealthStatus {
770770
timestamp: string;
771771
checks: {
772772
kafka: ComponentHealth;
773-
cosmosDb: ComponentHealth;
773+
mongoDb: ComponentHealth;
774774
storage: ComponentHealth;
775775
ruleEngine: ComponentHealth;
776776
dapr?: ComponentHealth;

src/services/encounter-service/k8s/encounter-service-deployment.yaml

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ metadata:
55
namespace: cloudhealthoffice
66
data:
77
ASPNETCORE_ENVIRONMENT: "Production"
8-
CosmosDb__DatabaseName: "CloudHealthOffice"
9-
CosmosDb__ContainerName: "Encounters"
8+
MongoDb__DatabaseName: "CloudHealthOffice"
109
---
1110
apiVersion: apps/v1
1211
kind: Deployment
@@ -18,7 +17,7 @@ metadata:
1817
tier: backend
1918
component: encounter-processing
2019
spec:
21-
replicas: 3
20+
replicas: 1
2221
selector:
2322
matchLabels:
2423
app: encounter-service
@@ -40,34 +39,18 @@ spec:
4039
- name: MongoDb__ConnectionString
4140
valueFrom:
4241
secretKeyRef:
43-
name: encounter-service-secret
44-
key: MongoDb__ConnectionString
45-
optional: true
42+
name: mongodb-secret
43+
key: connectionString
4644
- name: ASPNETCORE_ENVIRONMENT
4745
valueFrom:
4846
configMapKeyRef:
4947
name: encounter-service-config
5048
key: ASPNETCORE_ENVIRONMENT
51-
- name: CosmosDb__DatabaseName
49+
- name: MongoDb__DatabaseName
5250
valueFrom:
5351
configMapKeyRef:
5452
name: encounter-service-config
55-
key: CosmosDb__DatabaseName
56-
- name: CosmosDb__ContainerName
57-
valueFrom:
58-
configMapKeyRef:
59-
name: encounter-service-config
60-
key: CosmosDb__ContainerName
61-
- name: CosmosDb__Endpoint
62-
valueFrom:
63-
secretKeyRef:
64-
name: cosmos-db-secret
65-
key: endpoint
66-
- name: CosmosDb__Key
67-
valueFrom:
68-
secretKeyRef:
69-
name: cosmos-db-secret
70-
key: key
53+
key: MongoDb__DatabaseName
7154
resources:
7255
requests:
7356
cpu: 200m
@@ -115,7 +98,7 @@ spec:
11598
apiVersion: apps/v1
11699
kind: Deployment
117100
name: encounter-service
118-
minReplicas: 3
101+
minReplicas: 1
119102
maxReplicas: 20
120103
metrics:
121104
- type: Resource

src/services/reference-data-service/k8s/reference-data-service-deployment.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ metadata:
9090
name: reference-data-service
9191
namespace: cloudhealthoffice
9292
spec:
93-
replicas: 2
93+
replicas: 1
9494
selector:
9595
matchLabels:
9696
app: reference-data-service
@@ -155,7 +155,7 @@ spec:
155155
apiVersion: apps/v1
156156
kind: Deployment
157157
name: reference-data-service
158-
minReplicas: 2
158+
minReplicas: 1
159159
maxReplicas: 10
160160
metrics:
161161
- type: Resource

0 commit comments

Comments
 (0)