# MongoDB Setup for Gmail-Discord-Zammad Bridge ## Overview The bridge uses **MongoDB only** for persistent storage (tickets, transcripts, counters, tags, close requests). SQLite has been removed; a backup of the old SQLite-based code and schema lives in `backup-sqlite/`. To migrate existing SQLite data to MongoDB, run `npm run migrate-from-sqlite` (see that script’s prerequisites). ## Files Created 1. **`db-connection.js`** - MongoDB connection module with reconnection logic 2. **`models.js`** - Updated with three new schemas: - `Ticket` - Stores ticket information - `TicketCounter` - Tracks ticket numbers per sender - `Transcript` - Stores transcript message references 3. **`mongodb-example.js`** - Example usage patterns ## Configuration ### 1. Environment Variable Add to your `.env` file: ```env MONGODB_URI=mongodb://localhost:27018/indifferent_broccoli ``` **Note:** Uses port `27018` to match your existing Indifferent Broccoli setup (as defined in docker-compose.yml). ### 2. Install Dependencies ```bash npm install ``` This will install `mongoose@^6.12.0`. ## Usage in Your Code ### Basic Connection ```javascript const { connectMongoDB, closeMongoDB, mongoose } = require('./db-connection'); // In your Discord client.once('ready', ...) event: await connectMongoDB(process.env.MONGODB_URI); console.log('Connected to MongoDB'); // Get models: const Ticket = mongoose.model('Ticket'); const TicketCounter = mongoose.model('TicketCounter'); const Transcript = mongoose.model('Transcript'); ``` ### Replacing SQLite Operations #### Old (SQLite): ```javascript const ticket = await dbGet("SELECT * FROM tickets WHERE gmail_thread_id = ?", [threadId]); ``` #### New (MongoDB): ```javascript const Ticket = mongoose.model('Ticket'); const ticket = await Ticket.findOne({ gmail_thread_id: threadId }); ``` #### Old (SQLite): ```javascript await dbRun("INSERT INTO tickets (gmail_thread_id, discord_thread_id, ...) VALUES (?, ?, ...)", [threadId, channelId, ...]); ``` #### New (MongoDB): ```javascript const Ticket = mongoose.model('Ticket'); await Ticket.create({ gmail_thread_id: threadId, discord_thread_id: channelId, ... }); ``` #### Old (SQLite): ```javascript await dbRun("UPDATE tickets SET status = ? WHERE gmail_thread_id = ?", ['closed', threadId]); ``` #### New (MongoDB): ```javascript const Ticket = mongoose.model('Ticket'); await Ticket.updateOne( { gmail_thread_id: threadId }, { $set: { status: 'closed' } } ); ``` ## Schema Reference ### Ticket Schema ```javascript { gmail_thread_id: String (required, unique, indexed), discord_thread_id: String, zammad_ticket_id: Number, sender_email: String (required), subject: String, created_at: Date (default: now), status: String (enum: ['open', 'closed'], default: 'open'), claimed_by: String (Discord user ID), escalated: Boolean (default: false), ticket_number: Number, rename_count: Number (default: 0), rename_window_start: Date } ``` ### TicketCounter Schema ```javascript { sender_local: String (required, unique), counter: Number (default: 1) } ``` ### Transcript Schema ```javascript { gmail_thread_id: String (required), transcript_message_id: String, created_at: Date (default: now) } ``` ## Testing the Connection Run the example file to verify everything works: ```bash node mongodb-example.js ``` Expected output: ``` Connecting to MongoDB... ✓ Connected to MongoDB ✓ Models loaded: Ticket, TicketCounter, Transcript --- Example: Create Ticket --- Created ticket: example_thread_123 ... ✓ Example completed successfully ``` ## Graceful Shutdown Add this to your main file for clean shutdown: ```javascript process.on('SIGTERM', async () => { console.log('SIGTERM received, closing connections...'); await closeMongoDB(); await client.destroy(); // Discord client process.exit(0); }); process.on('SIGINT', async () => { console.log('SIGINT received, closing connections...'); await closeMongoDB(); await client.destroy(); process.exit(0); }); ``` ## Migration Notes - **No automatic data migration** from SQLite - starting fresh with MongoDB - The existing `tickets.sqlite` and `discord_only.sqlite` files remain untouched - You can manually export data from SQLite and import into MongoDB if needed ## Connection Features - **Auto-reconnection**: If MongoDB connection drops, Mongoose will automatically attempt to reconnect - **Connection events**: Logs when connected, disconnected, and reconnected - **Error handling**: Graceful error messages with stack traces - **Timeouts**: Configured with reasonable defaults (5s server selection, 45s socket timeout) ## Next Steps 1. Review the schemas in `models.js` (lines 793-819) 2. Test the connection with `node mongodb-example.js` 3. Start replacing SQLite operations in `zammad-discord.js` with MongoDB operations 4. Monitor MongoDB connection in production logs ## Troubleshooting ### Connection refused - Check MongoDB is running: `docker ps` or `systemctl status mongodb` - Verify port 27018 is correct in `.env` - Check MongoDB logs for errors ### Authentication failed - If MongoDB requires auth, update URI: `mongodb://username:password@localhost:27018/indifferent_broccoli` ### Schema validation errors - Check required fields are provided when creating documents - Ensure `status` is either 'open' or 'closed' (enum validation)