Feature: Option to use rqlite database storage (#254)

This commit is contained in:
Ralph Slooten
2024-04-05 15:48:32 +13:00
parent 5166a761ec
commit 254b2dd8ec
20 changed files with 276 additions and 203 deletions

View File

@@ -67,7 +67,7 @@ func GetMessages(w http.ResponseWriter, r *http.Request) {
res.Start = start
res.Messages = messages
res.Count = len(messages) // legacy - now undocumented in API specs
res.Count = float64(len(messages)) // legacy - now undocumented in API specs
res.Total = stats.Total
res.Unread = stats.Unread
res.Tags = stats.Tags
@@ -133,9 +133,9 @@ func Search(w http.ResponseWriter, r *http.Request) {
res.Start = start
res.Messages = messages
res.Count = len(messages) // legacy - now undocumented in API specs
res.Total = stats.Total // total messages in mailbox
res.MessagesCount = results
res.Count = float64(len(messages)) // legacy - now undocumented in API specs
res.Total = stats.Total // total messages in mailbox
res.MessagesCount = float64(results)
res.Unread = stats.Unread
res.Tags = stats.Tags
@@ -337,7 +337,11 @@ func GetHeaders(w http.ResponseWriter, r *http.Request) {
return
}
bytes, _ := json.Marshal(m.Header)
bytes, err := json.Marshal(m.Header)
if err != nil {
httpError(w, err.Error())
return
}
w.Header().Add("Content-Type", "application/json")
_, _ = w.Write(bytes)
@@ -428,11 +432,9 @@ func DeleteMessages(w http.ResponseWriter, r *http.Request) {
return
}
} else {
for _, id := range data.IDs {
if err := storage.DeleteOneMessage(id); err != nil {
httpError(w, err.Error())
return
}
if err := storage.DeleteMessages(data.IDs); err != nil {
httpError(w, err.Error())
return
}
}

View File

@@ -10,18 +10,18 @@ import (
// MessagesSummary is a summary of a list of messages
type MessagesSummary struct {
// Total number of messages in mailbox
Total int `json:"total"`
Total float64 `json:"total"`
// Total number of unread messages in mailbox
Unread int `json:"unread"`
Unread float64 `json:"unread"`
// Legacy - now undocumented in API specs but left for backwards compatibility.
// Removed from API documentation 2023-07-12
// swagger:ignore
Count int `json:"count"`
Count float64 `json:"count"`
// Total number of messages matching current query
MessagesCount int `json:"messages_count"`
MessagesCount float64 `json:"messages_count"`
// Pagination offset
Start int `json:"start"`

View File

@@ -78,11 +78,10 @@ func Run() {
type message struct {
ID string
Size int
Size float64
}
func handleClient(conn net.Conn) {
var (
user = ""
state = 1
@@ -92,7 +91,7 @@ func handleClient(conn net.Conn) {
defer func() {
if state == UPDATE {
for _, id := range toDelete {
_ = storage.DeleteOneMessage(id)
_ = storage.DeleteMessages([]string{id})
}
if len(toDelete) > 0 {
// update web UI to remove deleted messages
@@ -178,19 +177,19 @@ func handleClient(conn net.Conn) {
}
} else if cmd == "STAT" && state == TRANSACTION {
totalSize := 0
totalSize := float64(0)
for _, m := range messages {
totalSize = totalSize + m.Size
}
sendResponse(conn, fmt.Sprintf("+OK %d %d", len(messages), totalSize))
sendResponse(conn, fmt.Sprintf("+OK %d %d", len(messages), int64(totalSize)))
} else if cmd == "LIST" && state == TRANSACTION {
totalSize := 0
totalSize := float64(0)
for _, m := range messages {
totalSize = totalSize + m.Size
}
sendData(conn, fmt.Sprintf("+OK %d messages (%d octets)", len(messages), totalSize))
sendData(conn, fmt.Sprintf("+OK %d messages (%d octets)", len(messages), int64(totalSize)))
// print all sizes
for row, m := range messages {
@@ -200,7 +199,7 @@ func handleClient(conn net.Conn) {
sendData(conn, ".")
} else if cmd == "UIDL" && state == TRANSACTION {
totalSize := 0
totalSize := float64(0)
for _, m := range messages {
totalSize = totalSize + m.Size
}

View File

@@ -8,6 +8,7 @@ import (
"net/http"
"net/http/httptest"
"net/url"
"os"
"strings"
"testing"
@@ -204,11 +205,15 @@ func TestAPIv1Search(t *testing.T) {
func setup() {
logger.NoLogging = true
config.MaxMessages = 0
config.DataFile = ""
config.DataFile = os.Getenv("MP_DATA_FILE")
if err := storage.InitDB(); err != nil {
panic(err)
}
if err := storage.DeleteAllMessages(); err != nil {
panic(err)
}
}
func assertStatsEqual(t *testing.T, uri string, unread, total int) {
@@ -225,8 +230,8 @@ func assertStatsEqual(t *testing.T, uri string, unread, total int) {
return
}
assertEqual(t, unread, m.Unread, "wrong unread count")
assertEqual(t, total, m.Total, "wrong total count")
assertEqual(t, float64(unread), m.Unread, "wrong unread count")
assertEqual(t, float64(total), m.Total, "wrong total count")
}
func assertSearchEqual(t *testing.T, uri, query string, count int) {
@@ -246,7 +251,7 @@ func assertSearchEqual(t *testing.T, uri, query string, count int) {
return
}
assertEqual(t, count, m.MessagesCount, "wrong search results count")
assertEqual(t, float64(count), m.MessagesCount, "wrong search results count")
}
func insertEmailData(t *testing.T) {

View File

@@ -773,8 +773,8 @@
},
"DatabaseSize": {
"description": "Database size in bytes",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"LatestVersion": {
"description": "Latest Mailpit version",
@@ -782,8 +782,8 @@
},
"Messages": {
"description": "Total number of messages in the database",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"RuntimeStats": {
"description": "Runtime statistics",
@@ -796,33 +796,33 @@
},
"MessagesDeleted": {
"description": "Database runtime messages deleted",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"SMTPAccepted": {
"description": "Accepted runtime SMTP messages",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"SMTPAcceptedSize": {
"description": "Total runtime accepted messages size in bytes",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"SMTPIgnored": {
"description": "Ignored runtime SMTP messages (when using --ignore-duplicate-ids)",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"SMTPRejected": {
"description": "Rejected runtime SMTP messages",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"Uptime": {
"description": "Mailpit server uptime in seconds",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
}
}
},
@@ -836,8 +836,8 @@
},
"Unread": {
"description": "Total number of messages in the database",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"Version": {
"description": "Current Mailpit version",
@@ -868,8 +868,8 @@
},
"Size": {
"description": "Size in bytes",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
}
},
"x-go-package": "github.com/axllent/mailpit/internal/storage"
@@ -1176,8 +1176,8 @@
},
"Size": {
"description": "Message size in bytes",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"Subject": {
"description": "Message subject",
@@ -1268,8 +1268,8 @@
},
"Size": {
"description": "Message size in bytes (total)",
"type": "integer",
"format": "int64"
"type": "number",
"format": "double"
},
"Snippet": {
"description": "Message snippet includes up to 250 characters",
@@ -1310,8 +1310,8 @@
},
"messages_count": {
"description": "Total number of messages matching current query",
"type": "integer",
"format": "int64",
"type": "number",
"format": "double",
"x-go-name": "MessagesCount"
},
"start": {
@@ -1330,14 +1330,14 @@
},
"total": {
"description": "Total number of messages in mailbox",
"type": "integer",
"format": "int64",
"type": "number",
"format": "double",
"x-go-name": "Total"
},
"unread": {
"description": "Total number of unread messages in mailbox",
"type": "integer",
"format": "int64",
"type": "number",
"format": "double",
"x-go-name": "Unread"
}
},