import { RedisLiveSet } from "redis-liveset";
import { Set } from "immutable";
/**
 * Callback passed to ProcessCallback to be called when processing is done
 */
export declare type DoneCallback = (error?: Error | null, value?: any) => void;
/**
 * Job Processing function interface
 */
export declare type ProcessCallback<Job> = (job: Job, done: DoneCallback) => void;
/**
 * Queue topic name refined type
 */
export declare type QueueTopic = string & {
    _tag: "QueueTopic";
};
/**
 * QueueTopic constructor
 * @constructor
 */
export declare function QueueTopic(topic: string): QueueTopic;
/**
 * Consumer Group identifier refined type
 */
export declare type ConsumerGroupId = string & {
    _tag: "ConsumerGroupId";
};
/**
 * ConsumerGroupId constructor
 * @constructor
 */
export declare function ConsumerGroupId(groupId: string): ConsumerGroupId;
/**
 * {@Link Consumer} accepts messages
 */
export interface Consumer {
    /**
     * Add new Message/Task to queue
     * @param {Object} data
     */
    add(data: any): void;
}
/**
 * {@Link Producer} is a source of messages which can be consumed by attaching a callback function
 */
export interface Producer<Job> {
    /**
     * Attach queue processing handler with processing parallelism
     * @param {MultiConsumerQueue.ProcessCallback<Job>} fn callback
     * @param {number} n parallelism
     */
    process(fn: ProcessCallback<Job>, n?: number): void;
}
/**
 * {@Link Queue} is a {@Link Consumer} and a {@Link Producer}
 */
export interface Queue<Job> extends Producer<Job>, Consumer {
}
/**
 * A {@Link Consumer} which accepts message to different topics identified by a {@Link TopicName}
 */
export interface NamedConsumer {
    add(topic: QueueTopic, data: any): void;
}
/**
 * A {@Link Producer} which produces messages to different {@Link QueueTopic}
 */
export interface NamedProducer<Job> {
    /**
     * Attach queue processing handler for given topic name and parallelism
     * @param {QueueTopic} topic
     * @param {MultiConsumerQueue.ProcessCallback<Job>} fn
     * @param {number} n
     */
    process(topic: QueueTopic, fn: ProcessCallback<Job>, n?: number): void;
}
/**
 * A {@Link Queue} is a {@Link NamedProducer} and a {@Link NamedConsumer}
 */
export interface NamedQueue<Job> extends NamedProducer<Job>, NamedConsumer {
}
/**
 * Defines a {@Link Producer} than can be consumed by multiple groups idenified by {@Link ConsumerGroupId}
 *
 * All distinct groups will process same set of messages
 */
export interface MultiConsumerProducer<Job> {
    /**
     * Process jobs within group defined by groupId identifier
     * @param {ConsumerGroupId} groupId consumer group identifier
     * @param {MultiConsumerQueue.ProcessCallback<Job>} fn processing function
     * @param {number} n process parallelism, defaults to 1
     */
    process(groupId: ConsumerGroupId, fn: ProcessCallback<Job>, n?: number): void;
}
/**
 * A Queue type which may be consumed by multiple groups
 *
 * It also adds the ability to _unsubscribe_ specific consumer group when it is not going
 *  to consume Queue messages anymore, to avoid storing messages
 */
export interface MultiConsumerQueue<Job> extends Consumer, MultiConsumerProducer<Job> {
    /**
     * Removes consumer group for current topic
     * Use this for cleanup, replace process(groupId) with removeGroup(groupId), deploy for a while
     */
    removeGroup(groupId: ConsumerGroupId): this;
}
/**
 * Wraps a {@Link NamedQueue} with given name, exposing {@Link Queue} interface
 */
export declare class NamedQueueWrap<Job> implements Queue<Job> {
    private readonly _topic;
    private readonly _out;
    constructor(_topic: QueueTopic, _out: NamedQueue<Job>);
    add(data: any): void;
    process(fn: ProcessCallback<Job>, n?: number): void;
}
/**
 * Passes calls to out {@Link NamedQueue} but transforming input topic name using given map function
 */
export declare class DynamicallyNamedQueue<Job> implements NamedQueue<Job> {
    readonly topic: (t: QueueTopic) => QueueTopic;
    readonly out: NamedQueue<Job>;
    constructor(topic: (t: QueueTopic) => QueueTopic, out: NamedQueue<Job>);
    add(topic: QueueTopic, data: any): void;
    process(topic: QueueTopic, fn: ProcessCallback<Job>, n?: number): void;
}
/**
 * EventBus is a communication channel to publish/subscribe for messages by topics
 */
export interface EventBus<Job> {
    /**
     * Returns new EventBus topic queue instance
     */
    topic(topic: QueueTopic): MultiConsumerQueue<Job>;
}
/**
 * {@Link MultiConsumerQueue} implementation helper
 *
 * Dispatches messages from source Queue to out {@Link NamedQueue} using all group IDs
 *  (syncronized using a RedisLiveSet) as topic names
 */
export declare class MultiConsumerQueueImpl<Job> implements MultiConsumerQueue<Job> {
    private readonly _source;
    private readonly _out;
    private readonly _groups;
    private readonly _jobDataLens;
    private _lastGroupsSet;
    /**
     * @param _source queue to add and dispatch messages from
     * @param _out a named queue to attach final processors to using groupId as topic name
     * @param _groups live set to synchronize consumer groups across nodes
     * @param _jobDataLens lens to extract data from Job, to support multiple implementations
     */
    constructor(_source: Queue<Job>, _out: NamedQueue<Job>, _groups: RedisLiveSet<string>, _jobDataLens: (j: Job) => any, _lastGroupsSet?: Set<string>);
    /**
     * Create new job
     * @param {Object} data
     * @returns {Job}
     */
    add(data: any): void;
    /**
     * Subscribe for processing using given groupId
     *
     * All subscribers using same groupId will split messages processing
     * @param {ConsumerGroupId} groupId
     * @param {ProcessCallback<Job>} fn
     * @param {number} n
     */
    process(groupId: ConsumerGroupId, fn: ProcessCallback<Job>, n?: number): void;
    /**
     * Removes consumer group for current topic
     * Use this for cleanup, replace process(groupId) with removeGroup(groupId), deploy for a while
     */
    removeGroup(groupId: ConsumerGroupId): this;
}
/**
 * EventBus implementation
 */
export declare class EventBusImpl<Job> implements EventBus<Job> {
    private readonly _buildQueue;
    private _queueMap;
    /**
     * @param _buildQueue MultiConsumerQueue builder function
     */
    constructor(_buildQueue: (t: QueueTopic) => MultiConsumerQueue<Job>);
    topic(topic: QueueTopic): MultiConsumerQueue<Job>;
}
