Skip to content
Snippets Groups Projects
jobs.ts 2.22 KiB
Newer Older
Alexander Rose's avatar
Alexander Rose committed
/**
 * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
 *
 * Adapted from LiteMol
 * Copyright (c) 2016 - now David Sehnal, licensed under Apache 2.0, See LICENSE file for more info.
 */

import produce from 'immer'
Alexander Rose's avatar
Alexander Rose committed
import { filter } from 'rxjs/operators';

import { Controller } from '../controller'
import { JobEvents } from '../../event/basic';
import { Context } from '../../context/context';
import { Job } from '../../service/job';


export interface JobInfo {
    name: string;
    message: string;
    abort?: () => void
}

export interface JobsState {
    jobs: { [k: number]: JobInfo }
Alexander Rose's avatar
Alexander Rose committed
}

export class JobsController extends Controller<JobsState> {
    private updated(state: Job.State) {
        let isWatched = state.type === this.type;
        let jobs = this.latestState.jobs!;

        if (!isWatched) {
            if (jobs[state.jobId] !== undefined) {
                jobs = produce(jobs, _jobs => { delete _jobs[state.jobId] });
Alexander Rose's avatar
Alexander Rose committed
                this.setState({ jobs });
            }
            return;
        }

        jobs = produce(jobs, _jobs => {
            _jobs[state.jobId] = {
                name: state.name,
                message: state.message,
                abort: state.abort
            };
        })
Alexander Rose's avatar
Alexander Rose committed
        this.setState({ jobs });
    }

    private started(job: Job.Info) {
        this.setState({
            jobs: produce(this.latestState.jobs!, _jobs => {
                _jobs[job.id] = { name: job.name, message: 'Running...' }
            })
Alexander Rose's avatar
Alexander Rose committed
        });
    }

    private completed(taskId: number) {
        if (!this.latestState.jobs![taskId]) return;
Alexander Rose's avatar
Alexander Rose committed

        this.setState({
            jobs: produce(this.latestState.jobs!, _jobs => { delete _jobs[taskId] })
Alexander Rose's avatar
Alexander Rose committed
        });
    }

    constructor(context: Context, private type: Job.Type) {
        super(context, {
Alexander Rose's avatar
Alexander Rose committed
        });

        JobEvents.StateUpdated.getStream(this.context)
            .subscribe(e => this.updated(e.data));

        JobEvents.Started.getStream(this.context).pipe(
            filter(e => e.data.type === type))
            .subscribe(e => this.started(e.data));

        JobEvents.Completed.getStream(this.context)
            .subscribe(e => this.completed(e.data));
    }
}