Best Python code snippet using autotest_python
job-manager.test.js
Source:job-manager.test.js  
1// Switch these lines once there are useful utils2// const testUtils = require('./utils');3require('./utils');4const assert = require('assert');5const path = require('path');6const sinon = require('sinon');7const delay = require('delay');8const FakeTimers = require('@sinonjs/fake-timers');9const logging = require('@tryghost/logging');10const JobManager = require('../index');11const sandbox = sinon.createSandbox();12const jobModelInstance = {13    id: 'unique',14    get: (field) => {15        if (field === 'status') {16            return 'finished';17        }18    }19};20describe('Job Manager', function () {21    beforeEach(function () {22        sandbox.stub(logging, 'info');23        sandbox.stub(logging, 'warn');24        sandbox.stub(logging, 'error');25    });26    afterEach(function () {27        sandbox.restore();28    });29    it('public interface', function () {30        const jobManager = new JobManager({});31        should.exist(jobManager.addJob);32        should.exist(jobManager.hasExecutedSuccessfully);33        should.exist(jobManager.awaitCompletion);34    });35    describe('Add a job', function () {36        describe('Inline jobs', function () {37            it('adds a job to a queue', async function () {38                const spy = sinon.spy();39                const jobManager = new JobManager({40                    JobModel: sinon.stub().resolves()41                });42                jobManager.addJob({43                    job: spy,44                    data: 'test data',45                    offloaded: false46                });47                should(jobManager.queue.idle()).be.false();48                // give time to execute the job49                await delay(1);50                should(jobManager.queue.idle()).be.true();51                should(spy.called).be.true();52                should(spy.args[0][0]).equal('test data');53            });54            it('handles failed job gracefully', async function () {55                const spy = sinon.stub().throws();56                const jobManager = new JobManager({});57                jobManager.addJob({58                    job: spy,59                    data: 'test data',60                    offloaded: false61                });62                should(jobManager.queue.idle()).be.false();63                // give time to execute the job64                await delay(1);65                should(jobManager.queue.idle()).be.true();66                should(spy.called).be.true();67                should(spy.args[0][0]).equal('test data');68                should(logging.error.called).be.true();69            });70        });71        describe('Offloaded jobs', function () {72            it('fails to schedule for invalid scheduling expression', function () {73                const jobManager = new JobManager({});74                try {75                    jobManager.addJob({76                        at: 'invalid expression',77                        name: 'jobName'78                    });79                } catch (err) {80                    err.message.should.equal('Invalid schedule format');81                }82            });83            it('fails to schedule for no job name', function () {84                const jobManager = new JobManager({});85                try {86                    jobManager.addJob({87                        at: 'invalid expression',88                        job: () => {}89                    });90                } catch (err) {91                    err.message.should.equal('Name parameter should be present if job is a function');92                }93            });94            it('schedules a job using date format', async function () {95                const jobManager = new JobManager({});96                const timeInTenSeconds = new Date(Date.now() + 10);97                const jobPath = path.resolve(__dirname, './jobs/simple.js');98                const clock = FakeTimers.install({now: Date.now()});99                jobManager.addJob({100                    at: timeInTenSeconds,101                    job: jobPath,102                    name: 'job-in-ten'103                });104                should(jobManager.bree.timeouts['job-in-ten']).type('object');105                should(jobManager.bree.workers['job-in-ten']).type('undefined');106                // allow to run the job and start the worker107                await clock.nextAsync();108                should(jobManager.bree.workers['job-in-ten']).type('object');109                const promise = new Promise((resolve, reject) => {110                    jobManager.bree.workers['job-in-ten'].on('error', reject);111                    jobManager.bree.workers['job-in-ten'].on('exit', (code) => {112                        should(code).equal(0);113                        resolve();114                    });115                });116                // allow job to finish execution and exit117                clock.next();118                await promise;119                should(jobManager.bree.workers['job-in-ten']).type('undefined');120                clock.uninstall();121            });122            it('schedules a job to run immediately', async function () {123                const jobManager = new JobManager({});124                const clock = FakeTimers.install({now: Date.now()});125                const jobPath = path.resolve(__dirname, './jobs/simple.js');126                jobManager.addJob({127                    job: jobPath,128                    name: 'job-now'129                });130                should(jobManager.bree.timeouts['job-now']).type('object');131                // allow scheduler to pick up the job132                clock.tick(1);133                should(jobManager.bree.workers['job-now']).type('object');134                const promise = new Promise((resolve, reject) => {135                    jobManager.bree.workers['job-now'].on('error', reject);136                    jobManager.bree.workers['job-now'].on('exit', (code) => {137                        should(code).equal(0);138                        resolve();139                    });140                });141                await promise;142                should(jobManager.bree.workers['job-now']).type('undefined');143                clock.uninstall();144            });145            it('fails to schedule a job with the same name to run immediately one after another', async function () {146                const jobManager = new JobManager({});147                const clock = FakeTimers.install({now: Date.now()});148                const jobPath = path.resolve(__dirname, './jobs/simple.js');149                jobManager.addJob({150                    job: jobPath,151                    name: 'job-now'152                });153                should(jobManager.bree.timeouts['job-now']).type('object');154                // allow scheduler to pick up the job155                clock.tick(1);156                should(jobManager.bree.workers['job-now']).type('object');157                const promise = new Promise((resolve, reject) => {158                    jobManager.bree.workers['job-now'].on('error', reject);159                    jobManager.bree.workers['job-now'].on('exit', (code) => {160                        should(code).equal(0);161                        resolve();162                    });163                });164                await promise;165                should(jobManager.bree.workers['job-now']).type('undefined');166                (() => {167                    jobManager.addJob({168                        job: jobPath,169                        name: 'job-now'170                    });171                }).should.throw('Job #1 has a duplicate job name of job-now');172                clock.uninstall();173            });174            it('uses custom error handler when job fails', async function (){175                let job = function namedJob() {176                    throw new Error('job error');177                };178                const spyHandler = sinon.spy();179                const jobManager = new JobManager({errorHandler: spyHandler});180                jobManager.addJob({181                    job,182                    name: 'will-fail'183                });184                // give time to execute the job185                // has to be this long because in Node v10 the communication is186                // done through processes, which takes longer comparing to worker_threads187                // can be reduced to 100 when Node v10 support is dropped188                await delay(600);189                should(spyHandler.called).be.true();190                should(spyHandler.args[0][0].message).equal('job error');191                should(spyHandler.args[0][1].name).equal('will-fail');192            });193            it('uses worker message handler when job sends a message', async function (){194                const workerMessageHandlerSpy = sinon.spy();195                const jobManager = new JobManager({workerMessageHandler: workerMessageHandlerSpy});196                jobManager.addJob({197                    job: path.resolve(__dirname, './jobs/message.js'),198                    name: 'will-send-msg'199                });200                jobManager.bree.run('will-send-msg');201                jobManager.bree.workers['will-send-msg'].postMessage('hello from Ghost!');202                // Give time for worker (worker thread) <-> parent process (job manager) communication203                await delay(100);204                should(workerMessageHandlerSpy.called).be.true();205                should(workerMessageHandlerSpy.args[0][0].name).equal('will-send-msg');206                should(workerMessageHandlerSpy.args[0][0].message).equal('Worker received: hello from Ghost!');207            });208        });209    });210    describe('Add one off job', function () {211        it('throws if name parameter is not provided', async function () {212            const jobManager = new JobManager({});213            try {214                await jobManager.addOneOffJob({215                    job: () => {}216                });217                throw new Error('should have thrown');218            } catch (err) {219                should.equal(err.message, 'The name parameter is required for a one off job.');220            }221        });222        describe('Inline jobs', function () {223            it('adds job to the queue when it is a unique one', async function () {224                const spy = sinon.spy();225                const JobModel = {226                    findOne: sinon.stub().resolves(undefined),227                    add: sinon.stub().resolves()228                };229                const jobManager = new JobManager({JobModel});230                await jobManager.addOneOffJob({231                    job: spy,232                    name: 'unique name',233                    data: 'test data',234                    offloaded: false235                });236                assert.equal(JobModel.add.called, true);237            });238            it('does not add a job to the queue when it already exists', async function () {239                const spy = sinon.spy();240                const JobModel = {241                    findOne: sinon.stub().resolves(jobModelInstance),242                    add: sinon.stub().throws('should not be called')243                };244                const jobManager = new JobManager({JobModel});245                try {246                    await jobManager.addOneOffJob({247                        job: spy,248                        name: 'I am the only one',249                        data: 'test data',250                        offloaded: false251                    });252                    throw new Error('should not reach this point');253                } catch (error) {254                    assert.equal(error.message, 'A "I am the only one" one off job has already been executed.');255                }256            });257            it('sets a finished state on an inline job', async function () {258                const JobModel = {259                    findOne: sinon.stub()260                        .onCall(0)261                        .resolves(null)262                        .resolves({id: 'unique', name: 'successful-oneoff'}),263                    add: sinon.stub().resolves({name: 'successful-oneoff'}),264                    edit: sinon.stub().resolves({name: 'successful-oneoff'})265                };266                const jobManager = new JobManager({JobModel});267                jobManager.addOneOffJob({268                    job: async () => {269                        return await delay(10);270                    },271                    name: 'successful-oneoff',272                    offloaded: false273                });274                // allow job to get picked up and executed275                await delay(20);276                // tracks the job queued277                should(JobModel.add.args[0][0].status).equal('queued');278                should(JobModel.add.args[0][0].name).equal('successful-oneoff');279                // tracks the job started280                should(JobModel.edit.args[0][0].status).equal('started');281                should(JobModel.edit.args[0][0].started_at).not.equal(undefined);282                should(JobModel.edit.args[0][1].id).equal('unique');283                // tracks the job finish284                should(JobModel.edit.args[1][0].status).equal('finished');285                should(JobModel.edit.args[1][0].finished_at).not.equal(undefined);286                should(JobModel.edit.args[1][1].id).equal('unique');287            });288            it('sets a failed state on a job', async function () {289                const JobModel = {290                    findOne: sinon.stub()291                        .onCall(0)292                        .resolves(null)293                        .resolves({id: 'unique', name: 'failed-oneoff'}),294                    add: sinon.stub().resolves({name: 'failed-oneoff'}),295                    edit: sinon.stub().resolves({name: 'failed-oneoff'})296                };297                let job = function namedJob() {298                    throw new Error('job error');299                };300                const spyHandler = sinon.spy();301                const jobManager = new JobManager({errorHandler: spyHandler, JobModel});302                await jobManager.addOneOffJob({303                    job,304                    name: 'failed-oneoff',305                    offloaded: false306                });307                // give time to execute the job308                await delay(50);309                // tracks the job start310                should(JobModel.edit.args[0][0].status).equal('started');311                should(JobModel.edit.args[0][0].started_at).not.equal(undefined);312                should(JobModel.edit.args[0][1].id).equal('unique');313                // tracks the job failure314                should(JobModel.edit.args[1][0].status).equal('failed');315                should(JobModel.edit.args[1][1].id).equal('unique');316            });317            it('adds job to the queue after failing', async function () {318                const JobModel = {319                    findOne: sinon.stub()320                        .onCall(0)321                        .resolves(null)322                        .onCall(1)323                        .resolves({id: 'unique'})324                        .resolves({325                            id: 'unique',326                            get: (field) => {327                                if (field === 'status') {328                                    return 'failed';329                                }330                            }331                        }),332                    add: sinon.stub().resolves({}),333                    edit: sinon.stub().resolves()334                };335                let job = function namedJob() {336                    throw new Error('job error');337                };338                const spyHandler = sinon.spy();339                const jobManager = new JobManager({errorHandler: spyHandler, JobModel});340                await jobManager.addOneOffJob({341                    job,342                    name: 'failed-oneoff',343                    offloaded: false344                });345                // give time to execute the job and fail346                await delay(50);347                should(JobModel.edit.args[1][0].status).equal('failed');348                // simulate process restart and "fresh" slate to add the job349                jobManager.removeJob('failed-oneoff');350                await jobManager.addOneOffJob({351                    job,352                    name: 'failed-oneoff',353                    offloaded: false354                });355                // give time to execute the job and fail AGAIN356                await delay(50);357                should(JobModel.edit.args[3][0].status).equal('started');358                should(JobModel.edit.args[4][0].status).equal('failed');359            });360        });361        describe('Offloaded jobs', function () {362            it('adds job to the queue when it is a unique one', async function () {363                const spy = sinon.spy();364                const JobModel = {365                    findOne: sinon.stub().resolves(undefined),366                    add: sinon.stub().resolves()367                };368                const jobManager = new JobManager({JobModel});369                await jobManager.addOneOffJob({370                    job: spy,371                    name: 'unique name',372                    data: 'test data'373                });374                assert.equal(JobModel.add.called, true);375            });376            it('does not add a job to the queue when it already exists', async function () {377                const spy = sinon.spy();378                const JobModel = {379                    findOne: sinon.stub().resolves(jobModelInstance),380                    add: sinon.stub().throws('should not be called')381                };382                const jobManager = new JobManager({JobModel});383                try {384                    await jobManager.addOneOffJob({385                        job: spy,386                        name: 'I am the only one',387                        data: 'test data'388                    });389                    throw new Error('should not reach this point');390                } catch (error) {391                    assert.equal(error.message, 'A "I am the only one" one off job has already been executed.');392                }393            });394            it('sets a finished state on a job', async function () {395                const JobModel = {396                    findOne: sinon.stub()397                        .onCall(0)398                        .resolves(null)399                        .resolves({id: 'unique', name: 'successful-oneoff'}),400                    add: sinon.stub().resolves({name: 'successful-oneoff'}),401                    edit: sinon.stub().resolves({name: 'successful-oneoff'})402                };403                const jobManager = new JobManager({JobModel});404                await jobManager.addOneOffJob({405                    job: path.resolve(__dirname, './jobs/message.js'),406                    name: 'successful-oneoff'407                });408                // allow job to get picked up and executed409                await delay(50);410                jobManager.bree.workers['successful-oneoff'].postMessage('be done!');411                // allow the message to be passed around412                await delay(50);413                // tracks the job start414                should(JobModel.edit.args[0][0].status).equal('started');415                should(JobModel.edit.args[0][0].started_at).not.equal(undefined);416                should(JobModel.edit.args[0][1].id).equal('unique');417                // tracks the job finish418                should(JobModel.edit.args[1][0].status).equal('finished');419                should(JobModel.edit.args[1][0].finished_at).not.equal(undefined);420                should(JobModel.edit.args[1][1].id).equal('unique');421            });422            it('handles a failed job', async function () {423                const JobModel = {424                    findOne: sinon.stub()425                        .onCall(0)426                        .resolves(null)427                        .resolves(jobModelInstance),428                    add: sinon.stub().resolves({name: 'failed-oneoff'}),429                    edit: sinon.stub().resolves({name: 'failed-oneoff'})430                };431                let job = function namedJob() {432                    throw new Error('job error');433                };434                const spyHandler = sinon.spy();435                const jobManager = new JobManager({errorHandler: spyHandler, JobModel});436                await jobManager.addOneOffJob({437                    job,438                    name: 'failed-oneoff'439                });440                // give time to execute the job441                // has to be this long because in Node v10 the communication is442                // done through processes, which takes longer comparing to worker_threads443                // can be reduced to 100 when Node v10 support is dropped444                await delay(100);445                // still calls the original error handler446                should(spyHandler.called).be.true();447                should(spyHandler.args[0][0].message).equal('job error');448                should(spyHandler.args[0][1].name).equal('failed-oneoff');449                // tracks the job start450                should(JobModel.edit.args[0][0].status).equal('started');451                should(JobModel.edit.args[0][0].started_at).not.equal(undefined);452                should(JobModel.edit.args[0][1].id).equal('unique');453                // tracks the job failure454                should(JobModel.edit.args[1][0].status).equal('failed');455                should(JobModel.edit.args[1][1].id).equal('unique');456            });457        });458    });459    describe('Job execution progress', function () {460        it('checks if job has ever been executed', async function () {461            const JobModel = {462                findOne: sinon.stub()463                    .withArgs('solovei')464                    .onCall(0)465                    .resolves(null)466                    .onCall(1)467                    .resolves({468                        id: 'unique',469                        get: (field) => {470                            if (field === 'status') {471                                return 'finished';472                            }473                        }474                    })475                    .onCall(2)476                    .resolves({477                        id: 'unique',478                        get: (field) => {479                            if (field === 'status') {480                                return 'failed';481                            }482                        }483                    })484            };485            const jobManager = new JobManager({JobModel});486            let executed = await jobManager.hasExecutedSuccessfully('solovei');487            should.equal(executed, false);488            executed = await jobManager.hasExecutedSuccessfully('solovei');489            should.equal(executed, true);490            executed = await jobManager.hasExecutedSuccessfully('solovei');491            should.equal(executed, false);492        });493        it('can wait for job completion', async function () {494            const spy = sinon.spy();495            let status = 'queued';496            const jobWithDelay = async () => {497                await delay(80);498                status = 'finished';499                spy();500            };501            const JobModel = {502                findOne: sinon.stub()503                    // first call when adding a job504                    .withArgs('solovei')505                    .onCall(0)506                    // first call when adding a job507                    .resolves(null)508                    .onCall(1)509                    .resolves(null)510                    .resolves({511                        id: 'unique',512                        get: () => status513                    }),514                add: sinon.stub().resolves()515            };516            const jobManager = new JobManager({JobModel});517            await jobManager.addOneOffJob({518                job: jobWithDelay,519                name: 'solovei',520                offloaded: false521            });522            should.equal(spy.called, false);523            await jobManager.awaitCompletion('solovei');524            should.equal(spy.called, true);525        });526    });527    describe('Remove a job', function () {528        it('removes a scheduled job from the queue', async function () {529            const jobManager = new JobManager({});530            const timeInTenSeconds = new Date(Date.now() + 10);531            const jobPath = path.resolve(__dirname, './jobs/simple.js');532            jobManager.addJob({533                at: timeInTenSeconds,534                job: jobPath,535                name: 'job-in-ten'536            });537            jobManager.bree.config.jobs[0].name.should.equal('job-in-ten');538            await jobManager.removeJob('job-in-ten');539            should(jobManager.bree.config.jobs[0]).be.undefined;540        });541    });542    describe('Shutdown', function () {543        it('gracefully shuts down an inline jobs', async function () {544            const jobManager = new JobManager({});545            jobManager.addJob({546                job: require('./jobs/timed-job'),547                data: 200,548                offloaded: false549            });550            should(jobManager.queue.idle()).be.false();551            await jobManager.shutdown();552            should(jobManager.queue.idle()).be.true();553        });554        it('gracefully shuts down an interval job', async function () {555            const jobManager = new JobManager({});556            jobManager.addJob({557                at: 'every 5 seconds',558                job: path.resolve(__dirname, './jobs/graceful.js')559            });560            await delay(1); // let the job execution kick in561            should(Object.keys(jobManager.bree.workers).length).equal(0);562            should(Object.keys(jobManager.bree.timeouts).length).equal(0);563            should(Object.keys(jobManager.bree.intervals).length).equal(1);564            await jobManager.shutdown();565            should(Object.keys(jobManager.bree.intervals).length).equal(0);566        });567    });...recruitment.sagas.js
Source:recruitment.sagas.js  
1import {2  all,3  call,4  put,5  select,6  takeLatest,7  takeEvery,8} from "redux-saga/effects";9import { path, pathOr, prop, propOr } from "ramda";10import { toast } from "react-toastify";11import en from "../lang/en";12import {13  getDecisionFromClient,14  STATUS_NO_GO,15  DECISION_NO_GO,16} from "../utils/kanban";17import {18  GET_RECRUITMENT,19  updateClientCorporationsIds,20  updateClientCorporations,21  getJobOrders as getJobOrdersAction,22  updateJobOrders,23  getJobSubmissions as getJobSubmissionsAction,24  updateJobSubmissions,25  GET_RECRUITMENT_JOB_SUBMISSIONS,26  GET_RECRUITMENT_JOB_ORDERS,27  updateHrs,28  UPDATE_RECRUITMENT_JOB_SUBMISSION,29  setJobOrders,30  setJobSubmissions,31  CREATE_RECRUITMENT_JOB_SUBMISSION,32  DELETE_RECRUITMENT_JOB_SUBMISSION,33  removeJobSubmission,34} from "./recruitment.actions";35import {36  getTalentAcquisitionManagers,37  getJobSubmissions as getJobSubmissionsService,38  updateJobSubmission as updateJobSubmissionService,39  getCandidate,40  updateCandidateDecision,41  getClientCorporation,42} from "./recruitment.service";43import {44  getJobOrders as getJobOrdersService,45  createJobSubmission as createJobSubmissionService,46  getJobSubmission,47  deleteJobSubmission as deleteJobSubmissionService,48} from "../kanban/kanban.service";49import {50  getStateJobSubmissions as getStateJobSubmissionsKanban,51  deleteJobSubmission as deleteJobSubmissionKanban,52} from "../kanban/kanban.sagas";53export const getStateClientCorporation = (state, ccId) =>54  pathOr({}, ["recruitment", "clientCorporations", ccId], state);55export const getStateJobSubmissions = (state) =>56  pathOr({}, ["recruitment", "jobSubmissions"], state);57export const getStateJobSubmission = (state, joId) =>58  pathOr({}, ["recruitment", "jobSubmissions", joId], state);59export const getStateJobOrders = (state) =>60  pathOr({}, ["recruitment", "jobOrders"], state);61export const getStateJobOrder = (state, jobOrderId) =>62  pathOr({}, ["recruitment", "jobOrders", jobOrderId], state);63export function* getRecruitment() {64  yield call(getTams);65}66export function* getTams(start = 0) {67  try {68    const tamsResponse = yield call(getTalentAcquisitionManagers, start);69    const tamList = yield call(propOr, [], "data", tamsResponse);70    yield all(tamList.map((tam) => put(getJobOrdersAction(prop("id", tam)))));71    if (propOr(0, "count", tamsResponse) > 0)72      yield call(73        getTalentAcquisitionManagers,74        propOr(0, "start", tamsResponse) + propOr(0, "count", tamsResponse)75      );76  } catch (e) {77    //78  }79}80export function* getClientCorporations(tamId, jobOrders) {81  const ccList = [];82  const clientCorporations = yield all(83    jobOrders.reduce((acc, jo) => {84      const cc = prop("clientCorporation", jo);85      ccList.push(prop("id", cc));86      const jos = pathOr([], [prop("id", cc), "jobOrders"], acc).concat(87        prop("id", jo)88      );89      acc[prop("id", cc)] = {90        ...cc,91        jobOrders: jos,92      };93      return acc;94    }, {})95  );96  for (let ccId of ccList) {97    const ccResponse = yield call(getClientCorporation, ccId);98    const clientCorporation = propOr({}, "data", ccResponse);99    clientCorporations[ccId] = {100      ...clientCorporations[ccId],101      ...clientCorporation,102    };103  }104  yield put(updateClientCorporations(clientCorporations));105  yield put(updateClientCorporationsIds(ccList));106}107export function* getJobOrders(action, start = 0) {108  const tamId = prop("payload", action);109  try {110    const jobOrdersResponse = yield call(getJobOrdersService, tamId, start);111    const jobOrderList = yield call(propOr, [], "data", jobOrdersResponse);112    yield call(getClientCorporations, tamId, jobOrderList);113    const jobOrders = yield all(114      jobOrderList.reduce((acc, jo) => {115        acc[prop("id", jo)] = { ...jo, jobSubmissions: {} };116        return acc;117      }, {})118    );119    yield put(updateJobOrders(jobOrders));120    yield all(121      jobOrderList.map((jobOrder) =>122        put(123          getJobSubmissionsAction(124            prop("id", jobOrder),125            path(["clientCorporation", "id"], jobOrder)126          )127        )128      )129    );130    const newStart =131      propOr(0, "start", jobOrdersResponse) +132      propOr(0, "count", jobOrdersResponse);133    if (newStart < propOr(0, "total", jobOrdersResponse))134      yield call(getJobOrders, action, newStart);135  } catch (e) {136    //137  }138}139export function* getJobSubmissions(action, start = 0) {140  const { joId, ccId } = prop("payload", action);141  try {142    const jobSubmissionsResponse = yield call(143      getJobSubmissionsService,144      joId,145      start146    );147    const jsList = propOr([], "data", jobSubmissionsResponse);148    const jobOrders = {};149    const hrs = [];150    const jobSubmissions = yield all(151      jsList.reduce((acc, js) => {152        acc[prop("id", js)] = {153          ...js,154          clientCorporationId: ccId,155        };156        const joId = path(["jobOrder", "id"], js);157        const jojss = pathOr(158          [],159          [joId, "jobSubmissions", js.status],160          jobOrders161        ).concat([js.id]);162        jobOrders[joId] = {163          jobSubmissions: {164            ...pathOr({}, [joId, "jobSubmissions"], jobOrders),165            [js.status]: jojss,166          },167        };168        return acc;169      }, {})170    );171    for (let js of jsList) {172      const candidateResponse = yield call(173        getCandidate,174        path(["candidate", "id"], js)175      );176      const candidate = propOr({}, "data", candidateResponse);177      jobSubmissions[prop("id", js)].candidate = candidate;178      const hr = prop("owner", candidate);179      if (hr) hrs.push(hr);180    }181    yield put(updateJobSubmissions(jobSubmissions));182    yield put(updateJobOrders(jobOrders));183    yield put(updateHrs(hrs));184  } catch (e) {185    //186  }187}188export function* getDecision(jobOrderId, status) {189  const jo = yield select(getStateJobOrder, jobOrderId);190  const cc = yield select(191    getStateClientCorporation,192    path(["clientCorporation", "id"], jo)193  );194  if (status === STATUS_NO_GO) return DECISION_NO_GO;195  else return yield call(getDecisionFromClient, propOr("", "name", cc));196}197export function* updateJobSubmission(action) {198  const {199    payload: {200      prevStatus,201      jobSubmissionId,202      prevJobOrderId,203      jobOrderId,204      status,205    },206  } = action;207  const jobSubmission = yield select(getStateJobSubmission, jobSubmissionId);208  try {209    const decision = yield call(getDecision, jobOrderId, status);210    yield call(updateStateJobSubmission, {211      ...action,212      payload: {213        ...action.payload,214        decision,215        dateLastModified: new Date().getTime(),216      },217    });218    yield call(updateJobSubmissionService, jobSubmissionId, status, jobOrderId);219    yield call(toast.success, en.UPDATE_STATUS_SUCCESS);220  } catch (e) {221    const decision = yield call(getDecision, prevJobOrderId, prevStatus);222    yield call(updateStateJobSubmission, {223      ...action,224      payload: {225        ...action.payload,226        status: prevStatus,227        prevStatus: status,228        jobOrderId: prevJobOrderId,229        prevJobOrderId: jobOrderId,230        decision,231        dateLastModified: prop("dateLastModified", jobSubmission),232      },233    });234    yield call(toast.error, en.UPDATE_STATUS_ERROR);235  }236}237export function* updateStateJobSubmission(action) {238  const {239    payload: {240      prevJobOrderId,241      jobOrderId,242      prevStatus,243      jobSubmissionId,244      status,245      decision,246      dateLastModified,247    },248  } = action;249  const stateJobSubmissions = yield select(getStateJobSubmissions);250  const jobSubmission = stateJobSubmissions[jobSubmissionId];251  const stateNewJobOrder = yield select(getStateJobOrder, jobOrderId);252  const jobSubmissions = {253    ...stateJobSubmissions,254    [jobSubmissionId]: {255      ...jobSubmission,256      status,257      jobOrder: {258        id: prop("id", stateNewJobOrder),259        title: prop("title", stateNewJobOrder),260      },261      candidate: {262        ...jobSubmission.candidate,263        middleName: decision,264      },265      dateLastModified,266    },267  };268  yield put(setJobSubmissions(jobSubmissions));269  const statePrevJobOrder = yield select(getStateJobOrder, prevJobOrderId);270  const prevJojss = {271    ...prop("jobSubmissions", statePrevJobOrder),272    [prevStatus]: pathOr(273      [],274      ["jobSubmissions", prevStatus],275      statePrevJobOrder276    ).filter((jsId) => jsId !== jobSubmissionId),277  };278  const prevJobOrder = {279    [prevJobOrderId]: {280      ...statePrevJobOrder,281      jobSubmissions: prevJojss,282    },283  };284  const stateJobOrders1 = yield select(getStateJobOrders);285  yield put(setJobOrders({ ...stateJobOrders1, ...prevJobOrder }));286  const stateJobOrder = yield select(getStateJobOrder, jobOrderId);287  const jojss = {288    ...prop("jobSubmissions", stateJobOrder),289    [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).concat([290      jobSubmissionId,291    ]),292  };293  const jobOrder = {294    [jobOrderId]: {295      ...stateJobOrder,296      jobSubmissions: jojss,297    },298  };299  const stateJobOrders2 = yield select(getStateJobOrders);300  yield put(setJobOrders({ ...stateJobOrders2, ...jobOrder }));301}302export function* createJobSubmission(action) {303  const {304    payload: { jobOrder, jobSubmission, status },305  } = action;306  try {307    const js = {308      candidate: { id: path(["candidate", "id"], jobSubmission) },309      jobOrder: { id: prop("id", jobOrder) },310      status,311    };312    const putJobSubmissionResponse = yield call(createJobSubmissionService, js);313    const createdId = prop("changedEntityId", putJobSubmissionResponse);314    const jobSubmissionResponse = yield call(getJobSubmission, createdId);315    const candidateResponse = yield call(316      getCandidate,317      path(["candidate", "id"], jobSubmission)318    );319    const decision = yield call(getDecision, prop("id", jobOrder), status);320    const newJobSubmission = {321      ...propOr({}, "data", jobSubmissionResponse),322      bmId: prop("bmId", jobOrder),323      clientCorporationId: path(["clientCorporation", "id"], jobOrder),324      jobOrderId: prop("id", jobOrder),325      candidate: prop("data", candidateResponse),326    };327    yield call(addJobSubmission, newJobSubmission);328    yield call(toast.success, en.CREATE_CANDIDATE_SUCCESS);329    yield call(330      updateCandidateDecision,331      path(["candidate", "id"], jobSubmission),332      decision333    );334  } catch (e) {335    yield call(toast.error, en.CREATE_CANDIDATE_ERROR);336  }337}338export function* addJobSubmission(jobSubmission) {339  const jobSubmissionId = propOr("", "id", jobSubmission);340  const stateJobSubmissions = yield select(getStateJobSubmissions);341  var jobSubmissions = {342    ...stateJobSubmissions,343    [jobSubmissionId]: jobSubmission,344  };345  yield put(setJobSubmissions(jobSubmissions));346  const jobOrderId = path(["jobOrder", "id"], jobSubmission);347  const stateJobOrder = yield select(getStateJobOrder, jobOrderId);348  const status = prop("status", jobSubmission);349  const jojss = {350    ...prop("jobSubmissions", stateJobOrder),351    [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).concat([352      jobSubmissionId,353    ]),354  };355  const jobOrder = {356    [jobOrderId]: {357      ...stateJobOrder,358      jobSubmissions: jojss,359    },360  };361  const stateJobOrders = yield select(getStateJobOrders);362  yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }));363}364export function* deleteJobSubmissions(action) {365  const jobSubmission = prop("payload", action);366  const stateJobSubmissions = yield select(getStateJobSubmissions);367  const jobSubmissionsToDelete = Object.keys(stateJobSubmissions).filter(368    (jsId) =>369      path([jsId, "candidate", "id"], stateJobSubmissions) ===370      path(["candidate", "id"], jobSubmission)371  );372  for (let jsId of jobSubmissionsToDelete) {373    yield call(deleteJobSubmission, {374      payload: prop(jsId, stateJobSubmissions),375    });376  }377  const stateKanbanJobSubmissions = yield select(getStateJobSubmissionsKanban);378  const jobSubmissionsToDeleteInKanban = Object.keys(379    stateKanbanJobSubmissions380  ).filter(381    (jsId) =>382      path([jsId, "candidate", "id"], stateKanbanJobSubmissions) ===383      path(["candidate", "id"], jobSubmission)384  );385  for (let jsId of jobSubmissionsToDeleteInKanban) {386    yield call(deleteJobSubmissionKanban, {387      payload: prop(jsId, stateKanbanJobSubmissions),388    });389  }390}391export function* deleteJobSubmission(action) {392  const jobSubmission = prop("payload", action);393  const jobSubmissionId = prop("id", jobSubmission);394  const jobOrderId = path(["jobOrder", "id"], jobSubmission);395  const status = prop("status", jobSubmission);396  try {397    yield call(deleteJobSubmissionService, jobSubmissionId);398    yield put(removeJobSubmission(jobSubmissionId));399    const stateJobOrder = yield select(getStateJobOrder, jobOrderId);400    const jojss = {401      ...prop("jobSubmissions", stateJobOrder),402      [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).filter(403        (jsId) => jsId !== jobSubmissionId404      ),405    };406    const jobOrder = {407      [jobOrderId]: {408        ...stateJobOrder,409        jobSubmissions: jojss,410      },411    };412    const stateJobOrders = yield select(getStateJobOrders);413    yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }));414    yield call(toast.success, en.DELETE_JS_SUCCESS);415  } catch (e) {416    yield call(toast.error, en.DELETE_JS_ERROR);417  }418}419export default function kanbanSagas() {420  return [421    takeLatest(GET_RECRUITMENT, getRecruitment),422    takeEvery(GET_RECRUITMENT_JOB_ORDERS, getJobOrders),423    takeEvery(GET_RECRUITMENT_JOB_SUBMISSIONS, getJobSubmissions),424    takeEvery(UPDATE_RECRUITMENT_JOB_SUBMISSION, updateJobSubmission),425    takeEvery(CREATE_RECRUITMENT_JOB_SUBMISSION, createJobSubmission),426    takeEvery(DELETE_RECRUITMENT_JOB_SUBMISSION, deleteJobSubmissions),427  ];...kanban.sagas.js
Source:kanban.sagas.js  
1import { all, call, put, select, takeEvery, takeLatest } from "redux-saga/effects"2import { ascend, dissoc, path, pathOr, prop, propOr, sortWith } from "ramda"3import { toast } from "react-toastify"4import {5  GET_KANBAN,6  GET_JOB_ORDERS,7  GET_JOB_SUBMISSIONS,8  UPDATE_JOB_SUBMISSION,9  CREATE_JOB_SUBMISSION,10  DELETE_JOB_SUBMISSION,11  updateBms,12  updateClientCorporations,13  getJobOrders as getJobOrdersAction,14  setJobOrders,15  updateJobOrders,16  getJobSubmissions as getJobSubmissionsAction,17  setJobSubmissions,18  updateJobSubmissions,19  setBms,20  removeJobSubmission,21} from "./kanban.actions"22import {23  getBusinessManagers,24  getJobOrders as getJobOrdersService,25  getJobSubmissions as getJobSubmissionsService,26  updateJobSubmissionStatus as updateJobSubmissionStatusService,27  createJobSubmission as createJobSubmissionService,28  getJobSubmission,29  deleteJobSubmission as deleteJobSubmissionService,30} from "./kanban.service"31import en from "../lang/en"32import { filterJobOrdersPerPriority, getStateFilter } from "../priorityFilter/priorityFilter.sagas"33export const getStateBms = (state) => pathOr([], ["kanban", "bmList"], state)34export const getStateJobOrder = (state, joId) => pathOr({}, ["kanban", "jobOrders", joId], state)35export const getStateJobOrders = (state) => pathOr([], ["kanban", "jobOrders"], state)36export const getStateJobSubmissions = (state) => pathOr([], ["kanban", "jobSubmissions"], state)37export function* getKanbanBoard() {38  yield call(getBms)39}40export function* getBms(start = 0) {41  try {42    const bmsResponse = yield call(getBusinessManagers, start)43    const bmList = yield call(propOr, [], "data", bmsResponse)44    const bms = yield all(bmList.reduce((acc, bm) => ({ ...acc, [bm.id]: { ...bm, clientCorporations: [] } }), {}))45    yield put(updateBms(bms))46    yield all(bmList.map((bm) => put(getJobOrdersAction(prop("id", bm)))))47    const bmIds = yield all(bmList.map((bm) => prop("id", bm)))48    const stateBms = yield select(getStateBms)49    yield put(setBms(stateBms.concat(bmIds)))50    if (propOr(0, "count", bmsResponse) > 0)51      yield call(getBms, propOr(0, "start", bmsResponse) + propOr(0, "count", bmsResponse))52  } catch (e) {53    //54  }55}56export function* getClientCorporations(bmId, jobOrders) {57  const bms = {}58  const joClientCorporations = yield all(jobOrders.map((jo) => prop("clientCorporation", jo)))59  const clientCorporations = yield all(60    joClientCorporations.reduce((acc, jocc) => {61      const joccId = prop("id", jocc)62      if (!pathOr([], [bmId, "clientCorporations"], bms).find((ccId) => ccId === joccId)) {63        const bmcc = pathOr([], [bmId, "clientCorporations"], bms).concat([joccId])64        bms[bmId] = { clientCorporations: bmcc }65      }66      const clientCorporation = prop(joccId, acc)67      if (!clientCorporation) {68        acc[joccId] = { ...jocc, bmIds: { [bmId]: { jobOrders: [] } } }69      }70      return acc71    }, {})72  )73  yield put(updateClientCorporations(clientCorporations))74  yield put(updateBms(bms))75}76export function* getJobOrders(action, start = 0) {77  const bmId = action.payload78  try {79    const jobOrdersResponse = yield call(getJobOrdersService, bmId, start)80    const jobOrderList = yield call(propOr, [], "data", jobOrdersResponse)81    yield call(getClientCorporations, bmId, jobOrderList)82    const clientCorporations = {}83    const stateFilter = yield select(getStateFilter)84    const jobOrders = yield all(85      jobOrderList.reduce((acc, jobOrder) => {86        const ccId = path(["clientCorporation", "id"], jobOrder)87        const ccjos = pathOr([], [ccId, "bmIds", bmId, "jobOrders"], clientCorporations).concat([88          { id: jobOrder.id, employmentType: jobOrder.employmentType },89        ])90        const sortedCcjos = sortWith([ascend(prop("employmentType"))], ccjos)91        clientCorporations[ccId] = {92          bmIds: {93            [bmId]: {94              jobOrders: sortedCcjos,95              filteredJobOrders: filterJobOrdersPerPriority(sortedCcjos, stateFilter),96            },97          },98        }99        acc[jobOrder.id] = {100          ...jobOrder,101          bmId,102          clientCorporationId: ccId,103          jobSubmissions: {},104        }105        return acc106      }, {})107    )108    yield put(updateJobOrders(jobOrders))109    yield put(updateClientCorporations(clientCorporations))110    yield all(111      jobOrderList.map((jobOrder) =>112        put(getJobSubmissionsAction(bmId, path(["clientCorporation", "id"], jobOrder), prop("id", jobOrder)))113      )114    )115    const newStart = propOr(0, "start", jobOrdersResponse) + propOr(0, "count", jobOrdersResponse)116    if (newStart < propOr(0, "total", jobOrdersResponse)) yield call(getJobOrders, action, newStart)117  } catch (e) {118    //119  }120}121export function* getJobSubmissions(action, start = 0) {122  const {123    payload: { bmId, clientCorporationId, jobOrderId },124  } = action125  try {126    const jobOrders = {}127    const jobSubmissionsResponse = yield call(getJobSubmissionsService, jobOrderId, start)128    const jsList = propOr([], "data", jobSubmissionsResponse)129    const jobSubmissions = yield all(130      jsList.reduce((acc, js) => {131        const jojss = pathOr([], [jobOrderId, "jobSubmissions", js.status], jobOrders).concat([js.id])132        jobOrders[jobOrderId] = {133          jobSubmissions: {134            ...pathOr({}, [jobOrderId, "jobSubmissions"], jobOrders),135            [js.status]: jojss,136          },137        }138        acc[js.id] = {139          ...js,140          bmId,141          clientCorporationId,142          jobOrderId,143        }144        return acc145      }, {})146    )147    yield put(updateJobSubmissions(jobSubmissions))148    yield put(updateJobOrders(jobOrders))149    const newStart = propOr(0, "start", jobSubmissionsResponse) + propOr(0, "count", jobSubmissionsResponse)150    if (newStart < propOr(0, "total", jobSubmissionsResponse)) yield call(getJobSubmissions, action, newStart)151  } catch (e) {152    //153  }154}155export function* updateJobSubmission(action) {156  const {157    payload: { prevStatus, jobSubmissionId, status },158  } = action159  try {160    yield call(updateJobSubmissionStatus, action)161    yield call(updateJobSubmissionStatusService, jobSubmissionId, status)162    yield call(toast.success, en.UPDATE_STATUS_SUCCESS)163  } catch (e) {164    yield call(updateJobSubmissionStatus, {165      ...action,166      payload: { ...action.payload, status: prevStatus, prevStatus: status },167    })168    yield call(toast.error, en.UPDATE_STATUS_ERROR)169  }170}171export function* updateJobSubmissionStatus(action) {172  const {173    payload: { jobOrderId, prevStatus, jobSubmissionId, status },174  } = action175  const stateJobSubmissions = yield select(getStateJobSubmissions)176  const jobSubmission = stateJobSubmissions[jobSubmissionId]177  const jobSubmissions = {178    ...stateJobSubmissions,179    [jobSubmissionId]: {180      ...jobSubmission,181      status,182      dateLastModified: new Date().getTime(),183    },184  }185  yield put(setJobSubmissions(jobSubmissions))186  const stateJobOrder = yield select(getStateJobOrder, jobOrderId)187  const jojss = {188    ...prop("jobSubmissions", stateJobOrder),189    [prevStatus]: pathOr([], ["jobSubmissions", prevStatus], stateJobOrder).filter((jsId) => jsId !== jobSubmissionId),190    [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).concat([jobSubmissionId]),191  }192  const jobOrder = {193    [jobOrderId]: {194      ...stateJobOrder,195      jobSubmissions: jojss,196    },197  }198  const stateJobOrders = yield select(getStateJobOrders)199  yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }))200}201export const createTempId = (jobOrder, jobSubmission) =>202  `temp${prop("id", jobOrder)}${path(["candidate", "id"], jobSubmission)}`203export function* createJobSubmission(action) {204  const {205    payload: { jobOrder, jobSubmission, status },206  } = action207  const tempJs = {208    id: createTempId(jobOrder, jobSubmission),209    candidate: prop("candidate", jobSubmission),210    jobOrder,211    sendingUser: { id: prop("bmId", jobOrder) },212    status,213    bmId: prop("bmId", jobOrder),214    clientCorporationId: prop("clientCorporationId", jobOrder),215    jobOrderId: prop("id", jobOrder),216  }217  try {218    yield call(addJobSubmission, tempJs)219    const js = {220      candidate: { id: path(["candidate", "id"], jobSubmission) },221      jobOrder: { id: prop("id", jobOrder) },222      sendingUser: { id: prop("bmId", jobOrder) },223      status,224    }225    const putJobSubmissionResponse = yield call(createJobSubmissionService, js)226    const createdId = prop("changedEntityId", putJobSubmissionResponse)227    const jobSubmissionResponse = yield call(getJobSubmission, createdId)228    const newJobSubmission = {229      ...propOr({}, "data", jobSubmissionResponse),230      bmId: prop("bmId", jobOrder),231      clientCorporationId: prop("clientCorporationId", jobOrder),232      jobOrderId: prop("id", jobOrder),233    }234    yield call(addJobSubmission, newJobSubmission)235    yield call(toast.success, en.CREATE_CANDIDATE_SUCCESS)236  } catch (e) {237    yield call(removeTempJobSubmission, prop("id", tempJs))238    yield call(toast.error, en.CREATE_CANDIDATE_ERROR)239  }240}241export function* addJobSubmission(jobSubmission) {242  const jobSubmissionId = propOr("", "id", jobSubmission)243  const tempId = createTempId(prop("jobOrder", jobSubmission), jobSubmission)244  const stateJobSubmissions = yield select(getStateJobSubmissions)245  var jobSubmissions = {246    ...stateJobSubmissions,247    [jobSubmissionId]: jobSubmission,248  }249  if (!jobSubmissionId.toString().includes("temp")) jobSubmissions = dissoc(tempId, jobSubmissions)250  yield put(setJobSubmissions(jobSubmissions))251  const jobOrderId = path(["jobOrder", "id"], jobSubmission)252  const stateJobOrder = yield select(getStateJobOrder, jobOrderId)253  const status = prop("status", jobSubmission)254  const jojss = {255    ...prop("jobSubmissions", stateJobOrder),256    [status]: pathOr([], ["jobSubmissions", status], stateJobOrder)257      .filter((joId) => joId !== tempId)258      .concat([jobSubmissionId]),259  }260  const jobOrder = {261    [jobOrderId]: {262      ...stateJobOrder,263      jobSubmissions: jojss,264    },265  }266  const stateJobOrders = yield select(getStateJobOrders)267  yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }))268}269export function* removeTempJobSubmission(jobSubmission) {270  const jobSubmissionId = prop("id", jobSubmission)271  const stateJobSubmissions = yield select(getStateJobSubmissions)272  const jobSubmissions = dissoc(jobSubmissionId, stateJobSubmissions)273  yield put(setJobSubmissions(jobSubmissions))274  const jobOrderId = path(["jobOrder", "id"], jobSubmission)275  const stateJobOrder = yield select(getStateJobOrder, jobOrderId)276  const status = prop("status", jobSubmission)277  const jojss = {278    ...prop("jobSubmissions", stateJobOrder),279    [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).filter((jsId) => jsId !== jobSubmissionId),280  }281  const jobOrder = {282    [jobOrderId]: {283      ...stateJobOrder,284      jobSubmissions: jojss,285    },286  }287  const stateJobOrders = yield select(getStateJobOrders)288  yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }))289}290export function* deleteJobSubmission(action) {291  const jobSubmission = prop("payload", action)292  const jobSubmissionId = prop("id", jobSubmission)293  const jobOrderId = path(["jobOrder", "id"], jobSubmission)294  const status = prop("status", jobSubmission)295  try {296    yield call(deleteJobSubmissionService, jobSubmissionId)297    yield put(removeJobSubmission(jobSubmissionId))298    const stateJobOrder = yield select(getStateJobOrder, jobOrderId)299    const jojss = {300      ...prop("jobSubmissions", stateJobOrder),301      [status]: pathOr([], ["jobSubmissions", status], stateJobOrder).filter((jsId) => jsId !== jobSubmissionId),302    }303    const jobOrder = {304      [jobOrderId]: {305        ...stateJobOrder,306        jobSubmissions: jojss,307      },308    }309    const stateJobOrders = yield select(getStateJobOrders)310    yield put(setJobOrders({ ...stateJobOrders, ...jobOrder }))311    yield call(toast.success, en.DELETE_JS_SUCCESS)312  } catch (e) {313    yield call(toast.error, en.DELETE_JS_ERROR)314  }315}316export default function kanbanSagas() {317  return [318    takeLatest(GET_KANBAN, getKanbanBoard),319    takeEvery(GET_JOB_ORDERS, getJobOrders),320    takeEvery(GET_JOB_SUBMISSIONS, getJobSubmissions),321    takeEvery(UPDATE_JOB_SUBMISSION, updateJobSubmission),322    takeEvery(CREATE_JOB_SUBMISSION, createJobSubmission),323    takeEvery(DELETE_JOB_SUBMISSION, deleteJobSubmission),324  ]...JobDAG.py
Source:JobDAG.py  
1#* This file is part of the MOOSE framework2#* https://www.mooseframework.org3#*4#* All rights reserved, see COPYRIGHT for full restrictions5#* https://github.com/idaholab/moose/blob/master/COPYRIGHT6#*7#* Licensed under LGPL 2.1, please see LICENSE for details8#* https://www.gnu.org/licenses/lgpl-2.1.html9from schedulers.Job import Job10from contrib import dag11class JobDAG(object):12    """ Class which builds a Job DAG for use by the Scheduler """13    def __init__(self, options):14        self.__job_dag = dag.DAG()15        self.options = options16    def createJobs(self, testers):17        """ Return a usable Job DAG based on supplied list of tester objects """18        # for each tester, instance a job and create a DAG node for that job19        self.__name_to_job = {}20        for tester in testers:21            job = Job(tester, self.__job_dag, self.options)22            name = job.getUniqueIdentifier()23            if name not in self.__name_to_job:24                self.__name_to_job[name] = job25            else:26                job.addCaveats('duplicate test')27                job.setStatus(job.skip)28            self.__job_dag.add_node(job)29        return self._checkDAG()30    def getDAG(self):31        """ return the running DAG object """32        return self.__job_dag33    def getJobs(self):34        """ return current job group """35        return self.__job_dag.ind_nodes()36    def getJobsAndAdvance(self):37        """38        return finished jobs, and remove them from the DAG, thus39        advancing to the next set of jobs when called again.40        """41        # handle any skipped dependencies42        self._doSkippedDependencies()43        # delete finished jobs44        next_jobs = set([])45        for job in list(self.__job_dag.ind_nodes()):46            if job.isFinished():47                next_jobs.add(job)48                self.__job_dag.delete_node(job)49        next_jobs.update(self.getJobs())50        return next_jobs51    def removeAllDependencies(self):52        """ Flatten current DAG so that it no longer contains any dependency information """53        if self.__name_to_job and self.__job_dag.size():54            tmp_job_dag = dag.DAG()55            for job in self.__job_dag.topological_sort():56                tmp_job_dag.add_node(job)57            self.__job_dag = tmp_job_dag58        return self.__job_dag59    def _checkDAG(self):60        """ perform some sanity checks on the current DAG """61        if self.__job_dag.size():62            self._doMakeDependencies()63            self._doSkippedDependencies()64            # If there are race conditions, then there may be more skipped jobs65            if self._doRaceConditions():66                self._doSkippedDependencies()67        return self.__job_dag68    def _doMakeDependencies(self):69        """ Setup dependencies within the current Job DAG """70        for job in self.__job_dag.ind_nodes():71            prereq_jobs = job.getUniquePrereqs()72            for prereq_job in prereq_jobs:73                try:74                    self.__name_to_job[prereq_job]75                    self.__job_dag.add_edge(self.__name_to_job[prereq_job], job)76                # Cyclic errors77                except dag.DAGValidationError:78                    err_output = self._printDownstreams(job)79                    err_output += ' %s <--> %s' % (job.getTestName().split('.')[1],80                                                 self.__name_to_job[prereq_job].getTestName().split('.')[1])81                    job.setOutput('Cyclic dependency error!\n\t' + err_output)82                    job.setStatus(job.error, 'Cyclic or Invalid Dependency Detected!')83                # test file has invalid prereq set84                except KeyError:85                    job.setStatus(job.error, 'unknown dependency')86    def _doSkippedDependencies(self):87        """ Determine which jobs in the DAG should be skipped """88        for job in list(self.__job_dag.topological_sort()):89            tester = job.getTester()90            dep_jobs = set([])91            if not job.getRunnable() or self._haltDescent(job):92                job.setStatus(job.skip)93                dep_jobs.update(self.__job_dag.all_downstreams(job))94                # Remove parent dependency so it can launch individually95                for p_job in self.__job_dag.predecessors(job):96                    self.__job_dag.delete_edge_if_exists(p_job, job)97            for d_job in dep_jobs:98                d_tester = d_job.getTester()99                if tester.isSilent() and not d_job.getRunnable():100                    d_tester.setStatus(d_tester.silent)101                elif not self._skipPrereqs():102                    d_job.setStatus(d_job.skip)103                    d_job.addCaveats('skipped dependency')104                self.__job_dag.delete_edge_if_exists(job, d_job)105    def _doRaceConditions(self):106        """ Check for race condition errors within in the DAG"""107        # Build output_file in relation to job dictionary108        output_to_job = {}109        for job in self.__job_dag.topological_sort():110            if job.getRunnable() and not job.isFinished():111                for output_file in job.getOutputFiles():112                    output_to_job[output_file] = output_to_job.get(output_file, [])113                    output_to_job[output_file].append(job)114        # Remove jobs which have accurate dependencies115        for outfile, job_list in output_to_job.iteritems():116            for job in list(job_list):117                for match_job in self.__job_dag.all_downstreams(job):118                    if match_job in job_list:119                        job_list.remove(match_job)120        # Left over multiple items in job_list are problematic121        for outfile, job_list in output_to_job.iteritems():122            # Same test has duplicate output files123            if len(job_list) > 1 and len(set(job_list)) == 1:124                job_list[0].setOutput('Duplicate output files:\n\t%s\n' % (outfile))125                job_list[0].setStatus(job.error, 'DUPLICATE OUTFILES')126            # Multiple tests will clobber eachothers output file127            elif len(job_list) > 1:128                for job in job_list:129                    job.setOutput('Output file will over write pre-existing output file:\n\t%s\n' % (outfile))130                    job.setStatus(job.error, 'OUTFILE RACE CONDITION')131    def _haltDescent(self, job):132        """ return boolean if this job should not allow its children to run """133        tester = job.getTester()134        if (job.isFail()135            or job.isSkip()136            or tester.isFail()137            or tester.isSkip()138            or tester.isSilent()139            or tester.isDeleted()):140            return True141    def _skipPrereqs(self):142        """143        Method to return boolean to skip dependency prerequisites checks.144        """145        if (self.options.ignored_caveats146            and ('all' in self.options.ignored_caveats147                 or 'prereq' in self.options.ignored_caveats)):148            return True149    def _printDownstreams(self, job):150        """151        create a printable dependency chart of for supplied job152        # TODO: It would be super cool to print the entire DAG153                in this fashion.154        """155        downstreams = self.__job_dag.all_downstreams(job)156        cyclic_path = []157        for d_job in downstreams:158            cyclic_path.append('%s -->'% (d_job.getTestNameShort()))...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
