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 }