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

209 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```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)