chore: impl inbox store for mysql

This commit is contained in:
Steven 2023-10-28 09:44:52 +08:00
parent 480c53d7a2
commit 88fb79e458
10 changed files with 178 additions and 31 deletions

View File

@ -9,10 +9,10 @@ import (
// Version is the service current released version.
// Semantic versioning: https://semver.org/
var Version = "0.16.1"
var Version = "0.17.0"
// DevVersion is the service current development version.
var DevVersion = "0.16.1"
var DevVersion = "0.17.0"
func GetCurrentVersion(mode string) string {
if mode == "dev" || mode == "demo" {

View File

@ -2,26 +2,133 @@ package mysql
import (
"context"
"strings"
"github.com/pkg/errors"
"google.golang.org/protobuf/encoding/protojson"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store"
)
// nolint
func (d *DB) CreateInbox(ctx context.Context, create *store.Inbox) (*store.Inbox, error) {
return nil, nil
messageString := "{}"
if create.Message != nil {
bytes, err := protojson.Marshal(create.Message)
if err != nil {
return nil, errors.Wrap(err, "failed to marshal inbox message")
}
messageString = string(bytes)
}
fields := []string{"`sender_id`", "`receiver_id`", "`status`", "`message`"}
placeholder := []string{"?", "?", "?", "?"}
args := []any{create.SenderID, create.ReceiverID, create.Status, messageString}
stmt := "INSERT INTO `inbox` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ")"
result, err := d.db.ExecContext(ctx, stmt, args...)
if err != nil {
return nil, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
}
id32 := int32(id)
inbox, err := d.GetInbox(ctx, &store.FindInbox{ID: &id32})
if err != nil {
return nil, err
}
return inbox, nil
}
// nolint
func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.Inbox, error) {
return nil, nil
where, args := []string{"1 = 1"}, []any{}
if find.ID != nil {
where, args = append(where, "`id` = ?"), append(args, *find.ID)
}
if find.SenderID != nil {
where, args = append(where, "`sender_id` = ?"), append(args, *find.SenderID)
}
if find.ReceiverID != nil {
where, args = append(where, "`receiver_id` = ?"), append(args, *find.ReceiverID)
}
if find.Status != nil {
where, args = append(where, "`status` = ?"), append(args, *find.Status)
}
query := "SELECT `id`, UNIX_TIMESTAMP(`created_ts`), `sender_id`, `receiver_id`, `status`, `message` FROM `inbox` WHERE " + strings.Join(where, " AND ") + " ORDER BY `created_ts` DESC"
rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*store.Inbox{}
for rows.Next() {
inbox := &store.Inbox{}
var messageBytes []byte
if err := rows.Scan(
&inbox.ID,
&inbox.CreatedTs,
&inbox.SenderID,
&inbox.ReceiverID,
&inbox.Status,
&messageBytes,
); err != nil {
return nil, err
}
message := &storepb.InboxMessage{}
if err := protojsonUnmarshaler.Unmarshal(messageBytes, message); err != nil {
return nil, err
}
inbox.Message = message
list = append(list, inbox)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}
func (d *DB) GetInbox(ctx context.Context, find *store.FindInbox) (*store.Inbox, error) {
list, err := d.ListInboxes(ctx, find)
if err != nil {
return nil, errors.Wrap(err, "failed to get inbox")
}
if len(list) != 1 {
return nil, errors.Wrapf(nil, "unexpected inbox count: %d", len(list))
}
return list[0], nil
}
// nolint
func (d *DB) UpdateInbox(ctx context.Context, update *store.UpdateInbox) (*store.Inbox, error) {
return nil, nil
set, args := []string{"`status` = ?"}, []any{update.Status.String()}
args = append(args, update.ID)
query := "UPDATE `inbox` SET " + strings.Join(set, ", ") + " WHERE `id` = ?"
if _, err := d.db.ExecContext(ctx, query, args...); err != nil {
return nil, errors.Wrap(err, "failed to update inbox")
}
inbox, err := d.GetInbox(ctx, &store.FindInbox{ID: &update.ID})
if err != nil {
return nil, err
}
return inbox, nil
}
// nolint
func (d *DB) DeleteInbox(ctx context.Context, delete *store.DeleteInbox) error {
result, err := d.db.ExecContext(ctx, "DELETE FROM `inbox` WHERE `id` = ?", delete.ID)
if err != nil {
return errors.Wrap(err, "failed to delete inbox")
}
if _, err := result.RowsAffected(); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,9 @@
-- inbox
CREATE TABLE `inbox` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`sender_id` INT NOT NULL,
`receiver_id` INT NOT NULL,
`status` TEXT NOT NULL,
`message` TEXT NOT NULL
);

View File

@ -0,0 +1 @@
DELETE FROM `activity`;

View File

@ -11,6 +11,7 @@ DROP TABLE IF EXISTS `tag`;
DROP TABLE IF EXISTS `activity`;
DROP TABLE IF EXISTS `storage`;
DROP TABLE IF EXISTS `idp`;
DROP TABLE IF EXISTS `inbox`;
-- migration_history
CREATE TABLE `migration_history` (
@ -122,3 +123,13 @@ CREATE TABLE `idp` (
`identifier_filter` VARCHAR(256) NOT NULL DEFAULT '',
`config` TEXT NOT NULL
);
-- inbox
CREATE TABLE `inbox` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`created_ts` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`sender_id` INT NOT NULL,
`receiver_id` INT NOT NULL,
`status` TEXT NOT NULL,
`message` TEXT NOT NULL
);

View File

@ -49,8 +49,8 @@ func (d *DB) CreateUser(ctx context.Context, create *store.User) (*store.User, e
return nil, err
}
id64 := int32(id)
list, err := d.ListUsers(ctx, &store.FindUser{ID: &id64})
id32 := int32(id)
list, err := d.ListUsers(ctx, &store.FindUser{ID: &id32})
if err != nil {
return nil, err
}
@ -91,23 +91,10 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U
return nil, err
}
user := &store.User{}
query = "SELECT `id`, `username`, `role`, `email`, `nickname`, `password_hash`, `avatar_url`, UNIX_TIMESTAMP(`created_ts`), UNIX_TIMESTAMP(`updated_ts`), `row_status` FROM `user` WHERE `id` = ?"
if err := d.db.QueryRowContext(ctx, query, update.ID).Scan(
&user.ID,
&user.Username,
&user.Role,
&user.Email,
&user.Nickname,
&user.PasswordHash,
&user.AvatarURL,
&user.CreatedTs,
&user.UpdatedTs,
&user.RowStatus,
); err != nil {
user, err := d.GetUser(ctx, &store.FindUser{ID: &update.ID})
if err != nil {
return nil, err
}
return user, nil
}
@ -164,6 +151,17 @@ func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User
return list, nil
}
func (d *DB) GetUser(ctx context.Context, find *store.FindUser) (*store.User, error) {
list, err := d.ListUsers(ctx, find)
if err != nil {
return nil, err
}
if len(list) != 1 {
return nil, errors.Wrapf(nil, "unexpected user count: %d", len(list))
}
return list[0], nil
}
func (d *DB) DeleteUser(ctx context.Context, delete *store.DeleteUser) error {
result, err := d.db.ExecContext(ctx, "DELETE FROM `user` WHERE `id` = ?", delete.ID)
if err != nil {

View File

@ -25,7 +25,7 @@ func (d *DB) CreateInbox(ctx context.Context, create *store.Inbox) (*store.Inbox
placeholder := []string{"?", "?", "?", "?"}
args := []any{create.SenderID, create.ReceiverID, create.Status, messageString}
stmt := "INSERT INTO inbox (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`"
stmt := "INSERT INTO `inbox` (" + strings.Join(fields, ", ") + ") VALUES (" + strings.Join(placeholder, ", ") + ") RETURNING `id`, `created_ts`"
if err := d.db.QueryRowContext(ctx, stmt, args...).Scan(
&create.ID,
&create.CreatedTs,
@ -52,7 +52,7 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I
where, args = append(where, "`status` = ?"), append(args, *find.Status)
}
query := "SELECT `id`, `created_ts`, `sender_id`, `receiver_id`, `status`, `message` FROM `inbox` WHERE " + strings.Join(where, " AND ") + " ORDER BY created_ts DESC"
query := "SELECT `id`, `created_ts`, `sender_id`, `receiver_id`, `status`, `message` FROM `inbox` WHERE " + strings.Join(where, " AND ") + " ORDER BY `created_ts` DESC"
rows, err := d.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
@ -90,9 +90,9 @@ func (d *DB) ListInboxes(ctx context.Context, find *store.FindInbox) ([]*store.I
}
func (d *DB) UpdateInbox(ctx context.Context, update *store.UpdateInbox) (*store.Inbox, error) {
set, args := []string{"status"}, []any{update.Status.String()}
set, args := []string{"`status` = ?"}, []any{update.Status.String()}
args = append(args, update.ID)
query := "UPDATE inbox SET " + strings.Join(set, " = ?, ") + " = ? WHERE id = ? RETURNING `id`, `created_ts`, `sender_id`, `receiver_id`, `status`, `message`"
query := "UPDATE `inbox` SET " + strings.Join(set, ", ") + " WHERE `id` = ? RETURNING `id`, `created_ts`, `sender_id`, `receiver_id`, `status`, `message`"
inbox := &store.Inbox{}
var messageBytes []byte
if err := d.db.QueryRowContext(ctx, query, args...).Scan(
@ -114,7 +114,7 @@ func (d *DB) UpdateInbox(ctx context.Context, update *store.UpdateInbox) (*store
}
func (d *DB) DeleteInbox(ctx context.Context, delete *store.DeleteInbox) error {
result, err := d.db.ExecContext(ctx, "DELETE FROM inbox WHERE id = ?", delete.ID)
result, err := d.db.ExecContext(ctx, "DELETE FROM `inbox` WHERE `id` = ?", delete.ID)
if err != nil {
return err
}

View File

@ -0,0 +1,9 @@
-- inbox
CREATE TABLE inbox (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
sender_id INTEGER NOT NULL,
receiver_id INTEGER NOT NULL,
status TEXT NOT NULL,
message TEXT NOT NULL DEFAULT '{}'
);

View File

@ -0,0 +1 @@
DELETE FROM activity;

View File

@ -11,6 +11,7 @@ DROP TABLE IF EXISTS tag;
DROP TABLE IF EXISTS activity;
DROP TABLE IF EXISTS storage;
DROP TABLE IF EXISTS idp;
DROP TABLE IF EXISTS inbox;
-- migration_history
CREATE TABLE migration_history (
@ -133,3 +134,13 @@ CREATE TABLE idp (
identifier_filter TEXT NOT NULL DEFAULT '',
config TEXT NOT NULL DEFAULT '{}'
);
-- inbox
CREATE TABLE inbox (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
sender_id INTEGER NOT NULL,
receiver_id INTEGER NOT NULL,
status TEXT NOT NULL,
message TEXT NOT NULL DEFAULT '{}'
);