Files
broccolini-bot/MONGODB_SETUP.md
root 519788c633 Initial commit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 08:22:19 -06:00

5.3 KiB
Raw Blame History

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 scripts 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:

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

npm install

This will install mongoose@^6.12.0.

Usage in Your Code

Basic Connection

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):

const ticket = await dbGet("SELECT * FROM tickets WHERE gmail_thread_id = ?", [threadId]);

New (MongoDB):

const Ticket = mongoose.model('Ticket');
const ticket = await Ticket.findOne({ gmail_thread_id: threadId });

Old (SQLite):

await dbRun("INSERT INTO tickets (gmail_thread_id, discord_thread_id, ...) VALUES (?, ?, ...)", 
    [threadId, channelId, ...]);

New (MongoDB):

const Ticket = mongoose.model('Ticket');
await Ticket.create({
    gmail_thread_id: threadId,
    discord_thread_id: channelId,
    ...
});

Old (SQLite):

await dbRun("UPDATE tickets SET status = ? WHERE gmail_thread_id = ?", ['closed', threadId]);

New (MongoDB):

const Ticket = mongoose.model('Ticket');
await Ticket.updateOne(
    { gmail_thread_id: threadId },
    { $set: { status: 'closed' } }
);

Schema Reference

Ticket Schema

{
    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

{
    sender_local: String (required, unique),
    counter: Number (default: 1)
}

Transcript Schema

{
    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:

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:

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)