diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | cmd/daemon/main.go | 15 | ||||
| -rw-r--r-- | go.mod | 5 | ||||
| -rw-r--r-- | go.sum | 2 | ||||
| -rw-r--r-- | server/message.go | 4 | ||||
| -rw-r--r-- | server/server.go | 6 | ||||
| -rw-r--r-- | server/storage.go | 12 | ||||
| -rw-r--r-- | storage/storage.go | 61 | ||||
| -rw-r--r-- | storage/storage_test.go | 7 |
9 files changed, 109 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..884e3de --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +test.db
\ No newline at end of file diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go index bad350f..242a45a 100644 --- a/cmd/daemon/main.go +++ b/cmd/daemon/main.go @@ -11,11 +11,15 @@ import ( "strings" "go.rctt.net/solec/server" + "go.rctt.net/solec/storage" + + _ "github.com/mattn/go-sqlite3" ) var ( cmds = map[string]func(args []string){ "broadcast": sendBroadcast, + "exit": exit, } serv *server.Server ) @@ -28,7 +32,12 @@ func main() { name := flag.String("n", "localhost", "server name") flag.Parse() - serv = server.NewServer(*addr, *name) + db, err := storage.InitDb("test.db") + if err != nil { + panic(err) + } + + serv = server.NewServer(*addr, *name, db) serv.AddChannel("test") go func() { @@ -64,3 +73,7 @@ func sendBroadcast(args []string) { msg := strings.Join(args[0:], " ") serv.SendBroadcast(msg) } + +func exit(args []string) { + os.Exit(0) +} @@ -2,4 +2,7 @@ module go.rctt.net/solec go 1.26.1 -require github.com/google/go-cmp v0.7.0 +require ( + github.com/google/go-cmp v0.7.0 + github.com/mattn/go-sqlite3 v1.14.44 +) @@ -1,2 +1,4 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/mattn/go-sqlite3 v1.14.44 h1:3VSe+xafpbzsLbdr2AWlAZk9yRHiBhTBakioXaCKTF8= +github.com/mattn/go-sqlite3 v1.14.44/go.mod h1:pjEuOr8IwzLJP2MfGeTb0A35jauH+C2kbHKBr7yXKVQ= diff --git a/server/message.go b/server/message.go index 58f2908..11644dc 100644 --- a/server/message.go +++ b/server/message.go @@ -38,6 +38,10 @@ func (s *Server) handleMessage(sender net.Conn, msg core.Message) error { return err } + if err := s.storage.Write(msg); err != nil { + log.Println("cannot write to database", err) + } + if addr.Host == s.name { return s.handleLocalMessage(sender, addr, msg) } diff --git a/server/server.go b/server/server.go index ef2bb5f..74328a4 100644 --- a/server/server.go +++ b/server/server.go @@ -18,15 +18,17 @@ type Server struct { usersMu sync.RWMutex serversMu sync.RWMutex channelsMu sync.RWMutex + storage Storage } -func NewServer(listenAddr string, name string) *Server { +func NewServer(listenAddr string, name string, storage Storage) *Server { return &Server{ listenAddr: listenAddr, name: name, users: make(map[string]User), servers: make(map[string]RemoteServer), channels: make(map[string]*Channel), + storage: storage, } } @@ -50,7 +52,7 @@ func (s *Server) Start() error { func (s *Server) AddChannel(name string) { s.channelsMu.Lock() - s.channelsMu.Unlock() + defer s.channelsMu.Unlock() s.channels[name] = NewChannel(name) log.Println("created channel", name) } diff --git a/server/storage.go b/server/storage.go new file mode 100644 index 0000000..3473898 --- /dev/null +++ b/server/storage.go @@ -0,0 +1,12 @@ +package server + +import ( + "time" + + "go.rctt.net/solec/core" +) + +type Storage interface { + Write(msg core.Message) (err error) + Read(channel string, since time.Time, num, offset int) (history []core.Message, err error) +} diff --git a/storage/storage.go b/storage/storage.go new file mode 100644 index 0000000..9207761 --- /dev/null +++ b/storage/storage.go @@ -0,0 +1,61 @@ +package storage + +import ( + "database/sql" + "fmt" + "time" + + "go.rctt.net/solec/core" +) + +type Database struct { + *sql.DB +} + +const initSql = ` + CREATE TABLE IF NOT EXISTS messages + (id INTEGER NOT NULL PRIMARY KEY, source STRING, target STRING, timestamp INT, content STRING); +` + +func InitDb(path string) (*Database, error) { + db, err := sql.Open("sqlite3", path) + if err != nil { + return nil, err + } + + _, err = db.Exec(initSql) + return &Database{db}, nil +} + +func (db *Database) Write(msg core.Message) (err error) { + fmt.Println(msg.Timestamp) + + _, err = db.Exec( + "INSERT INTO messages (source, target, timestamp, content) VALUES (?, ?, ?, ?);", + msg.Source, msg.Target, msg.Timestamp.Unix(), msg.Content, + ) + + return err +} + +func (db *Database) Read(channel string, since time.Time, num int, offset int) (history []core.Message, err error) { + rows, err := db.Query( + "SELECT source, target, timestamp, content FROM messages WHERE timestamp > ? LIMIT ? OFFSET ?", + since.Unix(), num, offset, + ) + defer rows.Close() + + if err != nil { + return history, err + } + + for rows.Next() { + var msg core.Message + if err := rows.Scan(&msg.Source, &msg.Target, &msg.Timestamp, &msg.Content); err != nil { + return history, err + } + history = append(history, msg) + } + + return history, nil +} diff --git a/storage/storage_test.go b/storage/storage_test.go new file mode 100644 index 0000000..7a72c1f --- /dev/null +++ b/storage/storage_test.go @@ -0,0 +1,7 @@ +package storage + +import "testing" + +func TestStorage(t *testing.T) { + +} |
