Skip to content

Commit

Permalink
Merge pull request mailhog#1 from jay-dee7/jay-dee7/multi-tenanct-mongo
Browse files Browse the repository at this point in the history
Jay dee7/multi tenanct mongo
  • Loading branch information
jay-dee7 authored Oct 15, 2020
2 parents 6d871fb + e1bce2b commit 48c3608
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
language: go
go:
- 1.6
- 1.15
- tip
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/jay-dee7/storage

go 1.15

require (
github.com/mailhog/data v1.0.1 // indirect
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/mailhog/data v1.0.1 h1:7I+opBvVdi4EMJaihXavM98jp/ovt4o6mz47446RAW8=
github.com/mailhog/data v1.0.1/go.mod h1:tjR/iXRhbSUKHzAAMd99RygVaDB5rIDC/bmWc363MzU=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
2 changes: 1 addition & 1 deletion mongodb.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package storage

import (
"log"
"github.com/mailhog/data"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)

// MongoDB represents MongoDB backed storage backend
Expand Down
120 changes: 120 additions & 0 deletions mongodb_multi_tenant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package storage

import (
"github.com/mailhog/data"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)

// MongoDB represents MongoDB backed storage backend
type MultiTenantMongoDB struct {
database *mgo.Database
}

// CreateMongoDB creates a MongoDB backed storage backend
func CreateMultiTenantMongoDB(uri, db, coll string) *MultiTenantMongoDB {
log.Printf("Connecting to MongoDB: %s\n", uri)
session, err := mgo.Dial(uri)
if err != nil {
log.Printf("Error connecting to MongoDB: %s", err)
return nil
}
err = session.DB(db).C(coll).EnsureIndexKey("created")
if err != nil {
log.Printf("Failed creating index: %s", err)
return nil
}
return &MultiTenantMongoDB{
database: session.DB(db),
}
}

// Store stores a message in MongoDB and returns its storage ID
func (m *MultiTenantMongoDB) Store(msg *data.Message, tenant string) (string, error) {
err := m.database.C(tenant).Insert(m)
if err != nil {
log.Printf("Error inserting message: %s", err)
return "", err
}
return string(msg.ID), nil
}

// Count returns the number of stored messages
func (m *MultiTenantMongoDB) Count(tenant string) int {
c, _ := m.database.C(tenant).Count()
return c
}

// Search finds messages matching the query
func (m *MultiTenantMongoDB) Search(kind, query string, start, limit int, tenant string) (*data.Messages, int, error) {
messages := &data.Messages{}
var count = 0
var field = "raw.data"
switch kind {
case "to":
field = "raw.to"
case "from":
field = "raw.from"
}
err := m.database.C(tenant).Find(bson.M{field: bson.RegEx{Pattern: query, Options: "i"}}).Skip(start).Limit(limit).Sort("-created").Select(bson.M{
"id": 1,
"_id": 1,
"from": 1,
"to": 1,
"content.headers": 1,
"content.size": 1,
"created": 1,
"raw": 1,
}).All(messages)
if err != nil {
log.Printf("Error loading messages: %s", err)
return nil, 0, err
}
count, _ = m.database.C(tenant).Find(bson.M{field: bson.RegEx{Pattern: query, Options: "i"}}).Count()

return messages, count, nil
}

// List returns a list of messages by index
func (m *MultiTenantMongoDB) List(start int, limit int, tenant string) (*data.Messages, error) {
messages := &data.Messages{}
err := m.database.C(tenant).Find(bson.M{}).Skip(start).Limit(limit).Sort("-created").Select(bson.M{
"id": 1,
"_id": 1,
"from": 1,
"to": 1,
"content.headers": 1,
"content.size": 1,
"created": 1,
"raw": 1,
}).All(messages)
if err != nil {
log.Printf("Error loading messages: %s", err)
return nil, err
}
return messages, nil
}

// DeleteOne deletes an individual message by storage ID
func (m *MultiTenantMongoDB) DeleteOne(id, tenant string) error {
_, err := m.database.C(tenant).RemoveAll(bson.M{"id": id})
return err
}

// DeleteAll deletes all messages stored in MongoDB
func (m *MultiTenantMongoDB) DeleteAll(tenant string) error {
_, err := m.database.C(tenant).RemoveAll(bson.M{})
return err
}

// Load loads an individual message by storage ID
func (m *MultiTenantMongoDB) Load(id, tenant string) (*data.Message, error) {
result := &data.Message{}
err := m.database.C(tenant).Find(bson.M{"id": id}).One(&result)
if err != nil {
log.Printf("Error loading message: %s", err)
return nil, err
}
return result, nil
}
11 changes: 11 additions & 0 deletions storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,14 @@ type Storage interface {
DeleteAll() error
Load(id string) (*data.Message, error)
}

// Storage represents a storage backend
type MultiTenantStorage interface {
Store(m *data.Message, tenant string) (string, error)
List(start, limit int, tenant string) (*data.Messages, error)
Search(kind, query string, start, limit int, tenant string) (*data.Messages, int, error)
Count(tenant string) int
DeleteOne(id, tenant string) error
DeleteAll(tenant string) error
Load(id, tenant string) (*data.Message, error)
}

0 comments on commit 48c3608

Please sign in to comment.