-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage.go
96 lines (84 loc) · 2.05 KB
/
storage.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package storage
import (
"log/slog"
"os"
"path/filepath"
"github.com/glebarez/sqlite"
"github.com/rntrp/mailheap/internal/idsrc"
"github.com/rntrp/mailheap/internal/model"
"gorm.io/gorm"
)
type MailStorage interface {
AddMail(mail model.Mail) error
CountMails() (int64, error)
DeleteAllMails() (int64, error)
DeleteMails(ids ...int64) (int64, error)
GetMime(id int64) (string, error)
SeekMails(int64, int) ([]model.Mail, error)
Shutdown() error
}
type store struct {
db *gorm.DB
idSrc idsrc.IdSrc
}
func New() (MailStorage, error) {
path := filepath.Join(os.TempDir(), "mailheap.db")
f, err := os.OpenFile(path, os.O_CREATE, 0600)
if err != nil {
return nil, err
} else if err := f.Close(); err != nil {
slog.Warn("Closing db file failed:", "error", err.Error())
}
db, err := gorm.Open(sqlite.Open(path), new(gorm.Config))
if err != nil {
return nil, err
} else if err := db.AutoMigrate(new(model.Mail)); err != nil {
return nil, err
}
return &store{
db: db,
idSrc: idsrc.New(),
}, nil
}
func (s *store) AddMail(mail model.Mail) error {
id, err := s.idSrc.Gen()
if err != nil {
return err
}
mail.Id = id
s.db.Create(&mail)
return nil
}
func (s *store) CountMails() (int64, error) {
cnt := int64(0)
err := s.db.Model(new(model.Mail)).Count(&cnt).Error
return cnt, err
}
func (s *store) DeleteAllMails() (int64, error) {
tx := s.db.Delete(new(model.Mail), "id>=?", 0)
return tx.RowsAffected, tx.Error
}
func (s *store) DeleteMails(ids ...int64) (int64, error) {
tx := s.db.Delete(new(model.Mail), ids)
return tx.RowsAffected, tx.Error
}
func (s *store) GetMime(id int64) (string, error) {
m := new(model.Mail)
err := s.db.Select(model.Mime).First(m, id).Error
return m.Mime, err
}
func (s *store) SeekMails(afterId int64, limit int) ([]model.Mail, error) {
mails := make([]model.Mail, 0, limit)
err := s.db.Order("id DESC").
Limit(limit).
Find(&mails, "id<?", afterId).
Error
return mails, err
}
func (s *store) Shutdown() error {
if db, err := s.db.DB(); err != nil {
return err
} else {
return db.Close()
}
}