muthuk1 commited on
Commit
3ee46b0
·
verified ·
1 Parent(s): ed94e30

Upload integration/mlBottleneckScanner.js

Browse files
Files changed (1) hide show
  1. integration/mlBottleneckScanner.js +116 -0
integration/mlBottleneckScanner.js ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * ALWAS ML-Enhanced Bottleneck Scanner
3
+ * Drop-in replacement for the existing node-cron bottleneck scanner.
4
+ * Uses ML models instead of simple 48h threshold.
5
+ *
6
+ * Place in: server/cron/mlBottleneckScanner.js
7
+ *
8
+ * Setup in server/app.js:
9
+ * const cron = require('node-cron');
10
+ * const mlScanner = require('./cron/mlBottleneckScanner');
11
+ * cron.schedule('0 * * * *', () => mlScanner(io)); // hourly
12
+ */
13
+
14
+ const ml = require('../utils/alwas-ml-client');
15
+ const Block = require('../models/Block');
16
+ const Notification = require('../models/Notification');
17
+ const User = require('../models/User');
18
+
19
+ async function mlBottleneckScanner(io) {
20
+ console.log('[ML Scanner] Starting hourly bottleneck scan...');
21
+
22
+ try {
23
+ // Get all in-progress blocks
24
+ const blocks = await Block.find({
25
+ status: { $nin: ['Not Started', 'Completed'] }
26
+ }).populate('assignedTo');
27
+
28
+ let highRisk = 0;
29
+ let mediumRisk = 0;
30
+ let alerts = [];
31
+
32
+ for (const block of blocks) {
33
+ try {
34
+ // Calculate days in current stage
35
+ const lastTransition = block.transitions?.[block.transitions.length - 1];
36
+ const daysSince = lastTransition
37
+ ? (Date.now() - new Date(lastTransition.timestamp)) / (1000 * 60 * 60 * 24)
38
+ : 0;
39
+
40
+ const riskData = ml.constructor.formatForBottleneck(block, daysSince);
41
+ const risk = await ml.predictBottleneck(riskData);
42
+
43
+ if (risk.risk_level === 'High') {
44
+ highRisk++;
45
+
46
+ // Create notification for assigned engineer
47
+ if (block.assignedTo) {
48
+ const notification = await Notification.create({
49
+ user: block.assignedTo._id || block.assignedTo,
50
+ type: 'stuck',
51
+ message: `⚠️ ML Alert: ${block.name} has HIGH bottleneck risk`,
52
+ data: {
53
+ blockId: block._id,
54
+ risk: risk.risk_level,
55
+ confidence: risk.confidence,
56
+ recommendations: risk.recommendations,
57
+ hours_over_budget: risk.hours_over_budget_ratio,
58
+ }
59
+ });
60
+
61
+ // Real-time socket notification
62
+ io.emit('newNotification', {
63
+ userId: block.assignedTo._id || block.assignedTo,
64
+ notification: notification,
65
+ });
66
+ }
67
+
68
+ // Also notify managers
69
+ const managers = await User.find({ role: 'manager' });
70
+ for (const manager of managers) {
71
+ await Notification.create({
72
+ user: manager._id,
73
+ type: 'stuck',
74
+ message: `🔴 ML Bottleneck Alert: ${block.name} (${block.status}) — ${risk.recommendations[0] || 'High risk detected'}`,
75
+ data: {
76
+ blockId: block._id,
77
+ risk: risk.risk_level,
78
+ confidence: risk.confidence,
79
+ recommendations: risk.recommendations,
80
+ engineer: block.assignedTo?.name || 'Unassigned',
81
+ }
82
+ });
83
+ }
84
+
85
+ alerts.push({
86
+ block: block.name,
87
+ stage: block.status,
88
+ risk: risk.risk_level,
89
+ confidence: risk.confidence,
90
+ reason: risk.recommendations[0] || 'High risk',
91
+ });
92
+
93
+ } else if (risk.risk_level === 'Medium') {
94
+ mediumRisk++;
95
+ }
96
+ } catch (blockError) {
97
+ console.error(`[ML Scanner] Error scanning block ${block._id}:`, blockError.message);
98
+ }
99
+ }
100
+
101
+ console.log(`[ML Scanner] Scan complete: ${blocks.length} blocks scanned, ${highRisk} high risk, ${mediumRisk} medium risk`);
102
+
103
+ if (alerts.length > 0) {
104
+ console.log('[ML Scanner] High-risk blocks:');
105
+ alerts.forEach(a => console.log(` - ${a.block} (${a.stage}): ${a.reason}`));
106
+ }
107
+
108
+ return { scanned: blocks.length, highRisk, mediumRisk, alerts };
109
+
110
+ } catch (error) {
111
+ console.error('[ML Scanner] Fatal error:', error.message);
112
+ return { error: error.message };
113
+ }
114
+ }
115
+
116
+ module.exports = mlBottleneckScanner;