96 lines
3.4 KiB
JavaScript
96 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const mongoose = require('mongoose'),
|
|
Schema = mongoose.Schema,
|
|
PartnerLogTrackerStatus = require('../helpers/constants').PartnerLogTrackerStatus;
|
|
|
|
// Track processed partner logs to avoid duplicate processing
|
|
const partnerLogTrackerSchema = new Schema({
|
|
// Partner and aircraft identification
|
|
partnerCode: { type: String, required: true, trim: true }, // e.g., 'SATLOC'
|
|
aircraftId: { type: String, required: true, trim: true }, // Partner aircraft ID
|
|
customerId: { type: Schema.Types.ObjectId, ref: 'User', required: true },
|
|
|
|
// Log identification
|
|
logId: { type: String, required: true, trim: true }, // Partner log ID
|
|
logFileName: { type: String, required: true, trim: true }, // Log file name
|
|
uploadedDate: { type: String, required: false, trim: true }, // When log was uploaded to partner system (stored as-is, timezone unknown)
|
|
|
|
// Processing status with states to prevent race conditions
|
|
status: {
|
|
type: String,
|
|
enum: Object.values(PartnerLogTrackerStatus),
|
|
default: PartnerLogTrackerStatus.PENDING
|
|
},
|
|
processed: { type: Boolean, default: false },
|
|
processedAt: { type: Date, required: false },
|
|
enqueuedAt: { type: Date, required: false }, // When log was enqueued for processing
|
|
savedLocalFile: { type: String, required: false, trim: true }, // Filename only (path agnostic) - full path constructed from env SATLOC_STORAGE_PATH
|
|
processingStartedAt: { type: Date, required: false }, // When processing started (for timeout detection)
|
|
|
|
// Job matching
|
|
matchedJobs: [{
|
|
assignId: { type: Schema.Types.ObjectId, ref: 'Job_Assign' },
|
|
jobId: { type: Number, ref: 'Job' },
|
|
confidence: { type: Number, default: 1.0 } // Matching confidence 0-1
|
|
}],
|
|
|
|
// File processing results
|
|
appFileId: { type: Schema.Types.ObjectId, ref: 'AppFile' },
|
|
|
|
// Processing metadata
|
|
processTime: { type: Number, required: false }, // Processing time in ms
|
|
errorMessage: { type: String, required: false },
|
|
retryCount: { type: Number, default: 0 },
|
|
|
|
// Timestamps
|
|
createdAt: { type: Date, default: Date.now },
|
|
updatedAt: { type: Date, default: Date.now }
|
|
});
|
|
|
|
// Unique compound index for duplicate prevention
|
|
partnerLogTrackerSchema.index({
|
|
logId: 1,
|
|
partnerCode: 1
|
|
}, { unique: true });
|
|
|
|
// Compound index for worker queries: status-based filtering with time-based sorting
|
|
// Covers: stuck task detection, DLQ queries, status monitoring
|
|
// {status: 1, updatedAt: 1} can also use {status: 1, processingStartedAt: 1} for processingStartedAt queries
|
|
partnerLogTrackerSchema.index({
|
|
status: 1,
|
|
updatedAt: 1,
|
|
processingStartedAt: 1,
|
|
createdAt: 1,
|
|
retryCount: 1
|
|
});
|
|
|
|
// Compound index for customer-specific queries (admin dashboard, reports)
|
|
partnerLogTrackerSchema.index({
|
|
customerId: 1,
|
|
createdAt: -1
|
|
});
|
|
|
|
// Compound index for file download lookup with jobId optimization
|
|
// Covers both logFileName and savedLocalFile in one index using $or query
|
|
partnerLogTrackerSchema.index({
|
|
'matchedJobs.jobId': 1,
|
|
logFileName: 1,
|
|
savedLocalFile: 1
|
|
});
|
|
|
|
// Single-field index for filename-only lookup (fallback when jobId not provided)
|
|
// Covers both logFileName and savedLocalFile with one index
|
|
partnerLogTrackerSchema.index({
|
|
logFileName: 1,
|
|
savedLocalFile: 1
|
|
});
|
|
|
|
// Update the updatedAt field on save
|
|
partnerLogTrackerSchema.pre('save', function (next) {
|
|
this.updatedAt = new Date();
|
|
next();
|
|
});
|
|
|
|
module.exports = mongoose.model('Partner_Log_Tracker', partnerLogTrackerSchema);
|