feat: implement activity table

This commit is contained in:
Steven 2023-06-24 15:20:43 +08:00
parent 7057aec8c9
commit 81ac8d9c5d
4 changed files with 233 additions and 0 deletions

185
store/activity.go Normal file
View File

@ -0,0 +1,185 @@
package store
import (
"context"
"database/sql"
"strings"
)
type ActivityType string
const (
// ActivityShortcutView is the activity type of shortcut create.
ActivityShortcutCreate ActivityType = "shortcut.create"
// ActivityShortcutView is the activity type of shortcut view.
ActivityShortcutView ActivityType = "shortcut.view"
)
func (t ActivityType) String() string {
switch t {
case ActivityShortcutCreate:
return "shortcut.create"
case ActivityShortcutView:
return "shortcut.view"
}
return ""
}
type ActivityLevel string
const (
// ActivityInfo is the activity level of info.
ActivityInfo ActivityLevel = "INFO"
// ActivityWarn is the activity level of warn.
ActivityWarn ActivityLevel = "WARN"
// ActivityError is the activity level of error.
ActivityError ActivityLevel = "ERROR"
)
func (l ActivityLevel) String() string {
switch l {
case ActivityInfo:
return "INFO"
case ActivityWarn:
return "WARN"
case ActivityError:
return "ERROR"
}
return ""
}
type Activity struct {
ID int
CreatorID int
CreatedTs int64
Type ActivityType
Level ActivityLevel
Payload string
}
type FindActivity struct {
Type ActivityType
Level ActivityLevel
}
func (s *Store) CreateActivity(ctx context.Context, create *Activity) (*Activity, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
query := `
INSERT INTO activity (
creator_id,
type,
level,
payload
)
VALUES (?, ?, ?, ?)
RETURNING id, created_ts
`
if err := tx.QueryRowContext(ctx, query,
create.CreatorID,
create.Type.String(),
create.Level.String(),
create.Payload,
).Scan(
&create.ID,
&create.CreatedTs,
); err != nil {
return nil, err
}
if err := tx.Commit(); err != nil {
return nil, err
}
activity := create
return activity, nil
}
func (s *Store) ListActivities(ctx context.Context, find *FindActivity) ([]*Activity, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
list, err := listActivities(ctx, tx, find)
if err != nil {
return nil, err
}
return list, nil
}
func (s *Store) GetActivity(ctx context.Context, find *FindActivity) (*Activity, error) {
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, err
}
defer tx.Rollback()
list, err := listActivities(ctx, tx, find)
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
activity := list[0]
return activity, nil
}
func listActivities(ctx context.Context, tx *sql.Tx, find *FindActivity) ([]*Activity, error) {
where, args := []string{"1 = 1"}, []any{}
if find.Type != "" {
where, args = append(where, "type = ?"), append(args, find.Type.String())
}
if find.Level != "" {
where, args = append(where, "level = ?"), append(args, find.Level.String())
}
query := `
SELECT
id,
creator_id,
created_ts,
type,
level,
payload
FROM activity
WHERE ` + strings.Join(where, " AND ")
rows, err := tx.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*Activity{}
for rows.Next() {
activity := &Activity{}
if err := rows.Scan(
&activity.ID,
&activity.CreatorID,
&activity.CreatedTs,
&activity.Type,
&activity.Level,
&activity.Payload,
); err != nil {
return nil, err
}
list = append(list, activity)
}
if err := rows.Err(); err != nil {
return nil, err
}
return list, nil
}

View File

@ -43,3 +43,13 @@ CREATE TABLE shortcut (
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
tag TEXT NOT NULL DEFAULT ''
);
-- activity
CREATE TABLE activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
creator_id INTEGER NOT NULL,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
type TEXT NOT NULL DEFAULT '',
level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO',
payload TEXT NOT NULL DEFAULT '{}'
);

View File

@ -43,3 +43,13 @@ CREATE TABLE shortcut (
visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
tag TEXT NOT NULL DEFAULT ''
);
-- activity
CREATE TABLE activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
creator_id INTEGER NOT NULL,
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
type TEXT NOT NULL DEFAULT '',
level TEXT NOT NULL CHECK (level IN ('INFO', 'WARN', 'ERROR')) DEFAULT 'INFO',
payload TEXT NOT NULL DEFAULT '{}'
);

View File

@ -0,0 +1,28 @@
package teststore
import (
"context"
"testing"
"github.com/boojack/shortify/store"
"github.com/stretchr/testify/require"
)
func TestActivityStore(t *testing.T) {
ctx := context.Background()
ts := NewTestingStore(ctx, t)
list, err := ts.ListActivities(ctx, &store.FindActivity{})
require.NoError(t, err)
require.Equal(t, 0, len(list))
activity, err := ts.CreateActivity(ctx, &store.Activity{
CreatorID: -1,
Type: store.ActivityShortcutCreate,
Level: store.ActivityInfo,
Payload: "",
})
require.NoError(t, err)
list, err = ts.ListActivities(ctx, &store.FindActivity{})
require.NoError(t, err)
require.Equal(t, 1, len(list))
require.Equal(t, activity, list[0])
}