You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.0 KiB
Go
150 lines
3.0 KiB
Go
package remind
|
|
|
|
import (
|
|
"b612.me/sdk/candy/when"
|
|
"b612.me/stardb"
|
|
"b612.me/startimer"
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type Remind struct {
|
|
db *stardb.StarDB
|
|
tasks map[int]RemindTask
|
|
mu sync.RWMutex
|
|
callback func(remind RemindTask)
|
|
}
|
|
|
|
type RemindTask struct {
|
|
ID int `db:"id"`
|
|
Origin string `db:"text"`
|
|
timer *startimer.StarTimer
|
|
TmrInfo string `db:"code"`
|
|
Key string `db:"key"`
|
|
Msg []byte `db:"msg"`
|
|
}
|
|
|
|
func getCreateSql() []string {
|
|
return []string{
|
|
"CREATE TABLE IF NOT EXISTS remind(id INTEGER PRIMARY KEY AUTOINCREMENT,key VARCHAR(64),code TEXT,text TEXT,msg BLOB)",
|
|
"CREATE INDEX IF NOT EXISTS key_idx ON remind (key)",
|
|
}
|
|
}
|
|
|
|
func NewRemind(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, error) {
|
|
if db == nil || db.Db == nil {
|
|
return nil, errors.New("Invalid hanlder of database")
|
|
}
|
|
if err := db.Ping(); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, sql := range getCreateSql() {
|
|
_, err := db.Exec(sql)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return innerLoadDB(db, callback)
|
|
}
|
|
|
|
func innerLoadDB(db *stardb.StarDB, callback func(task RemindTask)) (*Remind, error) {
|
|
var rem = Remind{
|
|
db: db,
|
|
mu: sync.RWMutex{},
|
|
callback: callback,
|
|
}
|
|
var res []RemindTask
|
|
data, err := db.Query("select * from remind")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = data.Orm(&res)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(res) != 0 {
|
|
rem.tasks = make(map[int]RemindTask, len(res))
|
|
for _, task := range res {
|
|
tmr := startimer.NewTimer(time.Now())
|
|
err = tmr.ImportRepeats(task.TmrInfo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
task.timer = &tmr
|
|
task.timer.AddTask(func() {
|
|
rem.callbackFn(task)
|
|
})
|
|
err = task.timer.Run()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
rem.tasks[task.ID] = task
|
|
}
|
|
}
|
|
return &rem, nil
|
|
}
|
|
|
|
func (t RemindTask) GetTimer() startimer.StarTimer {
|
|
return *t.timer
|
|
}
|
|
func (r *Remind) callbackFn(task RemindTask) {
|
|
r.callback(task)
|
|
}
|
|
|
|
func (r *Remind) AddTask(taskStr, key string, msg []byte) (RemindTask, error) {
|
|
tmr, err := when.WhenWithPeriod(taskStr)
|
|
if err != nil {
|
|
return RemindTask{}, err
|
|
}
|
|
exp, err := tmr.ExportRepeats()
|
|
if err != nil {
|
|
return RemindTask{}, err
|
|
}
|
|
var rmt = RemindTask{
|
|
Origin: taskStr,
|
|
TmrInfo: exp,
|
|
Key: key,
|
|
Msg: msg,
|
|
timer: &tmr,
|
|
}
|
|
rmt.timer.AddTask(func() {
|
|
r.callbackFn(rmt)
|
|
})
|
|
res, err := r.db.Insert(rmt, "remind", "id")
|
|
if err != nil {
|
|
return RemindTask{}, err
|
|
}
|
|
id, err := res.LastInsertId()
|
|
if err != nil {
|
|
return RemindTask{}, err
|
|
}
|
|
rmt.ID = int(id)
|
|
r.mu.Lock()
|
|
r.tasks[rmt.ID] = rmt
|
|
r.mu.Unlock()
|
|
rmt.timer.Run()
|
|
return rmt, nil
|
|
}
|
|
|
|
func (r *Remind) DeleteTask(id int) error {
|
|
r.mu.RLock()
|
|
data, ok := r.tasks[id]
|
|
r.mu.RUnlock()
|
|
if !ok {
|
|
return errors.New("no such id")
|
|
}
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
err := data.timer.Stop()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = r.db.Exec("delete from remind where id=?", id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
delete(r.tasks, id)
|
|
return nil
|
|
}
|