func (d *Driver) Enqueue(queue string, id uid.ID, e *storage.Envelope, opts *storage.EnqueueOptions) (*storage.EnqueueMeta, error) { var meta storage.EnqueueMeta msgs := d.queues.get(queue) now := time.Now().UnixNano() d.m.Lock() defer d.m.Unlock() if opts.AccumTime > 0 { for _, msg := range *msgs { if msg.availAt > now && msg.accumlating { meta.AccumState = storage.AccumAdded msg.envelope.AddMessage(e.Messages[0]) return &meta, nil } } } msg := &message{ availAt: now, envelope: e, } if opts.AccumTime > 0 { msg.availAt += int64(opts.AccumTime) msg.accumlating = true meta.AccumState = storage.AccumStarted } heap.Push(msgs, msg) if opts.AccumTime == 0 { event.Emit(event.EventMessageAvailable, queue) } return &meta, nil }
func (d *Driver) Enqueue(queue string, id uid.ID, e *storage.Envelope, opts *storage.EnqueueOptions) (*storage.EnqueueMeta, error) { msg, err := marshal(e) if err != nil { return nil, err } var meta storage.EnqueueMeta if opts.AccumTime > 0 { now := time.Now().UnixNano() err = d.db.Update(func(tx *bolt.Tx) error { schedule := tx.Bucket(bucketSchedule) message := tx.Bucket(bucketMessage) if schedule == nil || message == nil { return ErrBucketNotFound } c := schedule.Cursor() for k, v := c.First(); k != nil; k, v = c.Next() { sk := scheduleKey(k) if sk.timestamp() <= now { continue } if sk.queue() == queue && sk.accumlating() { sd := scheduleData(v) b := message.Get(sd.messageID()) if b == nil { continue } meta.AccumState = storage.AccumAdded data := make([]byte, len(b)+len(msg)) n := copy(data, b) copy(data[n:], msg) return message.Put(sd.messageID(), data) } } return ErrMessageNotFound }) switch err { case nil: return &meta, nil case ErrMessageNotFound, ErrBucketNotFound: default: return nil, err } } skey := newScheduleKey(queue) if opts.AccumTime > 0 { skey.setAccumlating(true) meta.AccumState = storage.AccumStarted } sval := newScheduleData(id, int32(e.Retry), int64(e.Timeout)) for { t := time.Now().UnixNano() if opts.AccumTime > 0 { t += int64(opts.AccumTime) } skey.setTimestamp(t) err := d.db.Update(func(tx *bolt.Tx) error { message, err := tx.CreateBucketIfNotExists(bucketMessage) if err != nil { return err } schedule, err := tx.CreateBucketIfNotExists(bucketSchedule) if err != nil { return err } val := schedule.Get(skey) if val != nil { return errConflict } if err = message.Put(id.Bytes(), msg); err != nil { return err } return schedule.Put(skey, sval) }) if err == errConflict { continue } else if err == nil && opts.AccumTime == 0 { event.Emit(event.EventMessageAvailable, queue) } return &meta, err } }