CoolFace
Apppublic

sanket3280/code-execution

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
UserCode.js149 linesDownload Raw Back to models
1const mongoose = require('mongoose');2const zlib = require('zlib');3 4/**5 * OPTIMIZED UserCode Schema6 * 7 * One document per (user, problem, language) combination8 * 9 * Benefits:10 * - Small documents (10-20 KB vs 100-200 KB)11 * - Fast atomic updates (no array rewrite)12 * - Easy deletion (deleteOne vs $pull)13 * - Better indexing and query performance14 * - Optional compression for large code15 */16const UserCodeSchema = new mongoose.Schema({17  userId: {18    type: mongoose.Schema.Types.ObjectId,19    ref: 'User',20    required: true,21    index: true22  },23  challengeId: {24    type: mongoose.Schema.Types.ObjectId,25    ref: 'Challenge',26    default: null,  // null = practice mode27    index: true28  },29  problemId: {30    type: mongoose.Schema.Types.ObjectId,31    ref: 'Problem',32    required: true,33    index: true34  },35  language: {36    type: String,37    required: true,38    index: true39  },40  code: {41    type: String,42    default: '',43    validate: {44      validator: function(v) {45        return Buffer.byteLength(v, 'utf8') <= 102400; // 100KB limit46      },47      message: 'Code exceeds maximum size of 100KB'48    }49  },50  customInput: {51    type: String,52    default: ''53  },54  lastSavedAt: {55    type: Date,56    default: Date.now,57    index: true58  },59  clientTimestamp: {60    type: Date,61    default: Date.now62  },63  isSubmitted: {64    type: Boolean,65    default: false66  },67  deleted: {68    type: Boolean,69    default: false,70    index: true71  },72  // Optional: track if code is compressed73  isCompressed: {74    type: Boolean,75    default: false76  },77  createdAt: {78    type: Date,79    default: Date.now80  }81}, {82  timestamps: { updatedAt: true, createdAt: false }83});84 85// NEW: Compound unique index with challengeId - ensures one code per (user, challenge, problem, language)86// null challengeId is treated as a distinct value (practice mode)87UserCodeSchema.index(88  { userId: 1, challengeId: 1, problemId: 1, language: 1 },89  { unique: true }90);91 92// Index for cleanup queries93UserCodeSchema.index({ deleted: 1, lastSavedAt: 1 });94 95// Index for challenge deletion cascade96UserCodeSchema.index({ challengeId: 1 });97 98// TTL index - automatically delete documents after 2 days (172800 seconds)99UserCodeSchema.index(100  { lastSavedAt: 1 },101  { expireAfterSeconds: 172800 }102);103 104/**105 * Compress code before saving (optional)106 * Reduces storage by 40-60% for large code107 */108UserCodeSchema.methods.compressCode = function() {109  if (!this.isCompressed && this.code && this.code.length > 1000) {110    try {111      const compressed = zlib.gzipSync(this.code).toString('base64');112      this.code = compressed;113      this.isCompressed = true;114    } catch (err) {115      console.error('Compression failed:', err);116    }117  }118};119 120/**121 * Decompress code after loading122 */123UserCodeSchema.methods.decompressCode = function() {124  if (this.isCompressed && this.code) {125    try {126      const decompressed = zlib.gunzipSync(127        Buffer.from(this.code, 'base64')128      ).toString();129      this.code = decompressed;130      this.isCompressed = false;131    } catch (err) {132      console.error('Decompression failed:', err);133    }134  }135};136 137/**138 * Static method to get code with auto-decompression139 */140UserCodeSchema.statics.findAndDecompress = async function(query) {141  const doc = await this.findOne(query);142  if (doc && doc.isCompressed) {143    doc.decompressCode();144  }145  return doc;146};147 148// Export UserCode model149module.exports = mongoose.model('UserCode', UserCodeSchema);