Exemplo n.º 1
0
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
}
Exemplo n.º 2
0
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
	}
}