2023-10-27 01:10:19 +08:00
package mysql
import (
"context"
2024-01-11 21:29:22 +08:00
"database/sql"
2023-10-28 09:44:52 +08:00
"strings"
2023-10-27 01:10:19 +08:00
2023-10-28 09:44:52 +08:00
"github.com/pkg/errors"
"google.golang.org/protobuf/encoding/protojson"
storepb "github.com/usememos/memos/proto/gen/store"
2023-10-27 01:10:19 +08:00
"github.com/usememos/memos/store"
)
func ( d * DB ) CreateInbox ( ctx context . Context , create * store . Inbox ) ( * store . Inbox , error ) {
2023-10-28 09:44:52 +08:00
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
2023-10-27 01:10:19 +08:00
}
2023-10-28 00:08:42 +08:00
func ( d * DB ) ListInboxes ( ctx context . Context , find * store . FindInbox ) ( [ ] * store . Inbox , error ) {
2023-10-28 09:44:52 +08:00
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
2023-10-27 01:10:19 +08:00
}
func ( d * DB ) UpdateInbox ( ctx context . Context , update * store . UpdateInbox ) ( * store . Inbox , error ) {
2023-10-28 09:44:52 +08:00
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
2023-10-27 01:10:19 +08:00
}
func ( d * DB ) DeleteInbox ( ctx context . Context , delete * store . DeleteInbox ) error {
2023-10-28 09:44:52 +08:00
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
}
2023-10-27 01:10:19 +08:00
return nil
}
2024-01-11 21:29:22 +08:00
func vacuumInbox ( ctx context . Context , tx * sql . Tx ) error {
stmt := "DELETE FROM `inbox` WHERE `sender_id` NOT IN (SELECT `id` FROM `user`)"
_ , err := tx . ExecContext ( ctx , stmt )
if err != nil {
return err
}
return nil
}