job/queue.go
func (q *queue) Subscribe(
	subKeys []string, subID string, subFunc SubFunc) error {
	q.subsMtx.Lock()
	defer q.subsMtx.Unlock()

	for i, v := range subKeys {
		if err := q.subscribe(v, subID, subFunc); err != nil {
			for j := 0; j < i; j++ {
				q.unsubscribe(subKeys[j], subID)
			}
			return err
		}
	}

	return nil
}
func (q *queue) Subscribe(
	subKeys []string, subID string, subFunc SubFunc) error {
	q.subsMtx.Lock()
	defer q.subsMtx.Unlock()

	for i, v := range subKeys {
		if err := q.subscribe(v, subID, subFunc); err != nil {
			for j := 0; j < i; j++ {
				q.unsubscribe(subKeys[j], subID)
			}
			return err
		}
	}

	return nil
}
// Subscribe adds a subscription to job result notifications for given keys.
// Each subscription key can be be a job type or a job related id. SubID is
// used to distinguish between different subscriptions.