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', visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
tag TEXT NOT NULL DEFAULT '' 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', visibility TEXT NOT NULL CHECK (visibility IN ('PRIVATE', 'WORKSPACE', 'PUBLIC')) DEFAULT 'PRIVATE',
tag TEXT NOT NULL DEFAULT '' 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])
}