@startuml

class EventEmitter

Queue --|> EventEmitter
Queue "1" -right-> "*" Worker
Queue --> JobRepository

class Queue {
    + Queue(dbOptions: any)

    + createJob(string type, any data?): Job

    + process(type: string, processor: Function, concurrency: number): void
    + shutdown(timeout: number, type: string): Promise<void>

    + listAllJobs(): Job[]
    + listCompleteJobs(): Job[]
    + listFailedJobs(): Job[]
    + listInactiveJobs(): Job[]
    + listActiveJobs(): Job[]

    ~ findJob(type: string): Promise<Job>
    ~ addJob(job: Job): Promise<void>
    ~ updateJob(job: Job): Promise<void>
}

Job -left-> Queue

class Job {
    id: string

    <<readonly>> type: string
    <<get, set>> priority: Priority

    <<get>> createdAt: Date
    <<get>> updatedAt: Date
    <<get>> startedAt: Date
    <<get>> completedAt: Date
    <<get>> failedAt: Date

    <<get>> state: string
    <<get>> duration: number?
    <<get>> progress: number

    <<readonly>> data?: any
    <<get>> result?: any
    <<get>> progressResult?: any

    + Job(type: string)

    + setProgress(completed: number, total: number): Promise<void>
    + addLog(message :string): Promise<void>

    + save(): Promise<void>
    + update(): Promise<void>
    + remove(): Promise<void>

    ~ setStateToActive(): Promise<void>
    ~ setStateToComplete(): Promise<void>
    ~ setStateToFailed(): Promise<void>
}

Worker "1" -right-> "1" Job
Worker -left-> Queue

class Worker {
    <<readonly>> string type
    <<readonly>> bool isRunning
    <<readonly>> Job currentJob

    + void start(Processor processor)
    + void shutdown(number timeout)

    # Promise<Job | null> getJob()
    # Promise<void>  process(Processor processor)
}

class JobRepository {
    # db: NeDbDataStore
    # waitingWorkers: Object

    + init(): Promise<void>
    + findJob(type: string): Promise<Job>
    + addJob(job :Job): Promise<void>
    + updateJob(job: Job): Promise<void>
}

package enums {
    enum Priority {
        LOW
        NORMAL
        MEDIUM
        HIGH
        CRITICAL
    }

    enum State {
        INACTIVE
        ACTIVE
        COMPLETE
        FAILED
    }

    enum Event {
        enqueue
        start
        failed
        complete
        remove
        error
        progress
    }
}
@enduml
