UNPKG

5.62 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const configParser_1 = require("./configParser");
4/**
5 * The taskScheduler keeps track of the spec files that needs to run next
6 * and which task is running what.
7 */
8class TaskQueue {
9 // A queue of specs for a particular capacity
10 constructor(capabilities, specLists) {
11 this.capabilities = capabilities;
12 this.specLists = specLists;
13 this.numRunningInstances = 0;
14 this.specsIndex = 0;
15 this.maxInstance = capabilities.maxInstances || 1;
16 }
17}
18exports.TaskQueue = TaskQueue;
19class TaskScheduler {
20 /**
21 * A scheduler to keep track of specs that need running and their associated
22 * capabilities. It will suggest a task (combination of capabilities and spec)
23 * to run while observing the following config rules:
24 * multiCapabilities, shardTestFiles, and maxInstance.
25 * Precondition: multiCapabilities is a non-empty array
26 * (capabilities and getCapabilities will both be ignored)
27 *
28 * @constructor
29 * @param {Object} config parsed from the config file
30 */
31 constructor(config) {
32 this.config = config;
33 let excludes = configParser_1.ConfigParser.resolveFilePatterns(config.exclude, true, config.configDir);
34 let allSpecs = configParser_1.ConfigParser.resolveFilePatterns(configParser_1.ConfigParser.getSpecs(config), false, config.configDir)
35 .filter((path) => {
36 return excludes.indexOf(path) < 0;
37 });
38 let taskQueues = [];
39 config.multiCapabilities.forEach((capabilities) => {
40 let capabilitiesSpecs = allSpecs;
41 if (capabilities.specs) {
42 let capabilitiesSpecificSpecs = configParser_1.ConfigParser.resolveFilePatterns(capabilities.specs, false, config.configDir);
43 capabilitiesSpecs = capabilitiesSpecs.concat(capabilitiesSpecificSpecs);
44 }
45 if (capabilities.exclude) {
46 let capabilitiesSpecExcludes = configParser_1.ConfigParser.resolveFilePatterns(capabilities.exclude, true, config.configDir);
47 capabilitiesSpecs = capabilitiesSpecs.filter((path) => {
48 return capabilitiesSpecExcludes.indexOf(path) < 0;
49 });
50 }
51 let specLists = [];
52 // If we shard, we return an array of one element arrays, each containing
53 // the spec file. If we don't shard, we return an one element array
54 // containing an array of all the spec files
55 if (capabilities.shardTestFiles) {
56 capabilitiesSpecs.forEach((spec) => {
57 specLists.push([spec]);
58 });
59 }
60 else {
61 specLists.push(capabilitiesSpecs);
62 }
63 capabilities.count = capabilities.count || 1;
64 for (let i = 0; i < capabilities.count; ++i) {
65 taskQueues.push(new TaskQueue(capabilities, specLists));
66 }
67 });
68 this.taskQueues = taskQueues;
69 this.rotationIndex = 0; // Helps suggestions to rotate amongst capabilities
70 }
71 /**
72 * Get the next task that is allowed to run without going over maxInstance.
73 *
74 * @return {{capabilities: Object, specs: Array.<string>, taskId: string,
75 * done: function()}}
76 */
77 nextTask() {
78 for (let i = 0; i < this.taskQueues.length; ++i) {
79 let rotatedIndex = ((i + this.rotationIndex) % this.taskQueues.length);
80 let queue = this.taskQueues[rotatedIndex];
81 if (queue.numRunningInstances < queue.maxInstance &&
82 queue.specsIndex < queue.specLists.length) {
83 this.rotationIndex = rotatedIndex + 1;
84 ++queue.numRunningInstances;
85 let taskId = '' + rotatedIndex + 1;
86 if (queue.specLists.length > 1) {
87 taskId += '-' + queue.specsIndex;
88 }
89 let specs = queue.specLists[queue.specsIndex];
90 ++queue.specsIndex;
91 return {
92 capabilities: queue.capabilities,
93 specs: specs,
94 taskId: taskId,
95 done: function () {
96 --queue.numRunningInstances;
97 }
98 };
99 }
100 }
101 return null;
102 }
103 /**
104 * Get the number of tasks left to run or are currently running.
105 *
106 * @return {number}
107 */
108 numTasksOutstanding() {
109 let count = 0;
110 this.taskQueues.forEach((queue) => {
111 count += queue.numRunningInstances + (queue.specLists.length - queue.specsIndex);
112 });
113 return count;
114 }
115 /**
116 * Get maximum number of concurrent tasks required/permitted.
117 *
118 * @return {number}
119 */
120 maxConcurrentTasks() {
121 if (this.config.maxSessions && this.config.maxSessions > 0) {
122 return this.config.maxSessions;
123 }
124 else {
125 let count = 0;
126 this.taskQueues.forEach((queue) => {
127 count += Math.min(queue.maxInstance, queue.specLists.length);
128 });
129 return count;
130 }
131 }
132 /**
133 * Returns number of tasks currently running.
134 *
135 * @return {number}
136 */
137 countActiveTasks() {
138 let count = 0;
139 this.taskQueues.forEach((queue) => {
140 count += queue.numRunningInstances;
141 });
142 return count;
143 }
144}
145exports.TaskScheduler = TaskScheduler;
146//# sourceMappingURL=taskScheduler.js.map
\No newline at end of file