func (b *boltStorage) SaveNotification(n types.Notification) error {
	return b.db.Update(func(tx *bolt.Tx) error {
		b := getNBucket(tx)
		if err := b.Put(n.Key(), n.Value()); err != nil {
			return err
		}
		statusB := getSBucket(tx)
		bs := statusB.Get(keyNotification)
		num, _ := strconv.ParseUint(string(bs), 10, 64)
		err := statusB.Put(keyNotification, []byte(fmt.Sprint(num+1)))
		if err != nil {
			return err
		}
		bs = statusB.Get(keyToday(keyNotification))
		num, _ = strconv.ParseUint(string(bs), 10, 64)
		err = statusB.Put(keyToday(keyNotification), []byte(fmt.Sprint(num+1)))
		if err != nil {
			return err
		}
		relationBucket := getRBucket(tx)
		bs = relationBucket.Get([]byte(n.TaskID))
		notifications := make([]string, 0, 10)
		if len(bs) != 0 {
			if err := json.Unmarshal(bs, &notifications); err != nil {
				return err
			}
		}
		notifications = append(notifications, n.ID)
		bs, err = json.Marshal(notifications)
		if err != nil {
			return err
		}
		return relationBucket.Put([]byte(n.TaskID), bs)
	})
}
SaveNotification not only save to db but also update the task
package bolt
import (
	"encoding/json"
	"fmt"
	"sort"
	"strconv"
	"github.com/boltdb/bolt"
	"github.com/wrfly/et/storage"
	"github.com/wrfly/et/types"
)
type boltStorage struct {
	db *bolt.DB
}
func (b *boltStorage) SaveTask(t *types.Task) error {
	return b.db.Update(func(tx *bolt.Tx) error {
		b := getTBucket(tx)
		if err := b.Put(t.Key(), t.Value()); err != nil {
			return err
		}
		statusB := getSBucket(tx)
		bs := statusB.Get(keyTaskSubmit)
		num, _ := strconv.ParseUint(string(bs), 10, 64)
		if err := statusB.Put(keyTaskSubmit,
			[]byte(fmt.Sprint(num+1))); err != nil {
			return err
		}
		bs = statusB.Get(keyToday(keyTaskSubmit))
		num, _ = strconv.ParseUint(string(bs), 10, 64)
		if err := statusB.Put(keyToday(keyTaskSubmit),
			[]byte(fmt.Sprint(num+1))); err != nil {
			return err
		}
		return nil
	})
}
func (b *boltStorage) FindTask(ID string) (*types.Task, error) {
	t := &types.Task{}
	return t, b.db.View(func(tx *bolt.Tx) error {
		b := getTBucket(tx)
		bs := b.Get([]byte(ID))
		if bs == nil {
			return storage.ErrTaskNotFound
		}
		t.Unmarshal(bs)
		return nil
	})
}