diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js index d9e2613a58132f50781ac231ee4e5102332502c2..b148112a09416472a9093ba56d3a547f163724f3 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Timeline/CalendarTimeline.js @@ -6,7 +6,7 @@ import Timeline, { DateHeader, CustomMarker, CursorMarker, - CustomHeader + // CustomHeader } from 'react-calendar-timeline'; import containerResizeDetector from 'react-calendar-timeline/lib/resize-detector/container'; import moment from 'moment'; @@ -266,7 +266,7 @@ export class CalendarTimeline extends Component { <div className="sidebar-header-row">{this.state.dayHeaderVisible?`LST(Hr)`:`LST(Day)`}</div> {/* {this.state.viewType === UIConstants.timeline.types.NORMAL && */} <div className="p-grid legend-row" - style={{height:this.props.showSunTimings?'30px':'0px'}}> + style={{height:this.props.showSunTimings?'0px':'0px'}}> <div className="col-4 legend-suntime legend-sunrise">Sunrise</div> <div className="col-4 legend-suntime legend-sunset">Sunset</div> <div className="col-4 legend-suntime legend-night">Night</div> @@ -859,8 +859,9 @@ export class CalendarTimeline extends Component { setNormalSuntimings(startTime, endTime) { let sunRiseTimings = [], sunSetTimings = [], sunTimeMap={}; const noOfDays = endTime.diff(startTime, 'days'); - for (const number of _.range(noOfDays+1)) { - const date = startTime.clone().add(number, 'days').hours(12).minutes(0).seconds(0); + for (const number of _.range(noOfDays+3)) { // Added 3 to have suntimes of day before start time and day after end time so that for small time duration also, suntimes will be available. + let prevStartTime = startTime.clone().add(-1, 'days'); + const date = prevStartTime.clone().add(number, 'days').hours(12).minutes(0).seconds(0); const formattedDate = date.format("YYYY-MM-DD"); UtilService.getSunTimings(formattedDate).then(timings => { if (timings) { @@ -870,12 +871,12 @@ export class CalendarTimeline extends Component { const sunsetEndTime = moment.utc(timings.sun_set.end.split('.')[0]); const sunriseTime = {start: sunriseStartTime, end: sunriseEndTime}; const sunsetTime = {start: sunsetStartTime, end: sunsetEndTime}; - if (moment.utc(timings.sunriseEndTime).isAfter(startTime)) { + // if (moment.utc(timings.sunriseEndTime).isAfter(startTime)) { sunRiseTimings.push(sunriseTime); - } - if (moment.utc(timings.sunsetStartTime).isBefore(endTime)) { + // } + // if (moment.utc(timings.sunsetStartTime).isBefore(endTime)) { sunSetTimings.push(sunsetTime); - } + // } sunTimeMap[formattedDate] = {sunrise: sunriseTime, sunset: sunsetTime}; this.setState({sunRiseTimings: sunRiseTimings, sunSetTimings: sunSetTimings, sunTimeMap: sunTimeMap}); } @@ -1394,12 +1395,12 @@ export class CalendarTimeline extends Component { // <DateHeader unit={this.state.lstDateHeaderUnit} intervalRenderer={this.renderLSTDateHeader}></DateHeader> } {/* Suntime Header in normal view with sunrise, sunset and night time */} - {this.props.showSunTimings && this.state.viewType === UIConstants.timeline.types.NORMAL && this.state.sunTimeMap && + {/* {this.props.showSunTimings && this.state.viewType === UIConstants.timeline.types.NORMAL && this.state.sunTimeMap && <CustomHeader height={30} unit="minute" children={({ headerContext: { intervals }, getRootProps, getIntervalProps, showPeriod, data})=> { return this.renderNormalSuntimeHeader({ headerContext: { intervals }, getRootProps, getIntervalProps, showPeriod, data})}}> </CustomHeader> - } + } */} </TimelineHeaders> <TimelineMarkers> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js index 5a25a62050f2652843210ebe61992ffb126ac661..2f84cfb6c326ad7daaf3b9f56cb0fb78519053ed 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/ViewSchedulingUnit.js @@ -18,6 +18,7 @@ import { Redirect } from 'react-router-dom'; import { CustomDialog } from '../../layout/components/CustomDialog'; import { CustomPageSpinner } from '../../components/CustomPageSpinner'; import { Growl } from 'primereact/components/growl/Growl'; +import TaskService from '../../services/task.service'; class ViewSchedulingUnit extends Component{ constructor(props){ @@ -106,6 +107,7 @@ class ViewSchedulingUnit extends Component{ if (schedule_type && schedule_id) { this.stations = await ScheduleService.getStationGroup(); this.setState({stationOptions: this.stations}); + this.subtaskTemplates = await TaskService.getSubtaskTemplates(); this.getSchedulingUnitDetails(schedule_type, schedule_id); } } @@ -119,33 +121,31 @@ class ViewSchedulingUnit extends Component{ }; getSchedulingUnitDetails(schedule_type, schedule_id) { - this.getScheduleUnit(schedule_type, schedule_id) + ScheduleService.getSchedulingUnitExtended(schedule_type, schedule_id) .then(schedulingUnit =>{ if (schedulingUnit) { ScheduleService.getSchedulingConstraintTemplates().then((response) => { this.constraintTemplates = response; this.setState({ constraintSchema: this.constraintTemplates.find(i => i.id === schedulingUnit.scheduling_constraints_template_id) }) }); - this.getScheduleUnitTasks(schedule_type, schedulingUnit) - .then(tasks =>{ - tasks.map(task => { + let tasks = schedulingUnit.task_drafts?this.getFormattedTaskDrafts(schedulingUnit):this.getFormattedTaskBlueprints(schedulingUnit); + tasks.map(task => { task.status_logs = task.tasktype === "Blueprint"?this.subtaskComponent(task):""; //Displaying SubTask ID of the 'control' Task const subTaskIds = task.subTasks?task.subTasks.filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1):[]; task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; return task; - }); - const targetObservation = _.find(tasks, (task)=> {return task.template.type_value==='observation' && task.tasktype.toLowerCase()===schedule_type && task.specifications_doc.station_groups}); - this.setState({ - scheduleunitId: schedule_id, - scheduleunit : schedulingUnit, - scheduleunitType: schedule_type, - schedule_unit_task : tasks, - isLoading: false, - stationGroup: targetObservation?targetObservation.specifications_doc.station_groups:[], - redirect: null, - dialogVisible: false - }, this.getAllStations); + }); + const targetObservation = _.find(tasks, (task)=> {return task.template.type_value==='observation' && task.tasktype.toLowerCase()===schedule_type && task.specifications_doc.station_groups}); + this.setState({ + scheduleunitId: schedule_id, + scheduleunit : schedulingUnit, + scheduleunitType: schedule_type, + schedule_unit_task : tasks, + isLoading: false, + stationGroup: targetObservation?targetObservation.specifications_doc.station_groups:[], + redirect: null, + dialogVisible: false }); } else { this.setState({ @@ -168,6 +168,85 @@ class ViewSchedulingUnit extends Component{ } } + /** + * Formatting the task_drafts and task_blueprints in draft view to pass to the ViewTable component + * @param {Object} schedulingUnit - scheduling_unit_draft object from extended API call loaded with tasks(draft & blueprint) along with their template and subtasks + */ + getFormattedTaskDrafts(schedulingUnit) { + let scheduletasklist=[]; + // Common keys for Task and Blueprint + let commonkeys = ['id','created_at','description','name','tags','updated_at','url','do_cancel','relative_start_time','relative_stop_time','start_time','stop_time','duration','status']; + for(const task of schedulingUnit.task_drafts){ + let scheduletask = []; + scheduletask['tasktype'] = 'Draft'; + scheduletask['actionpath'] = '/task/view/draft/'+task['id']; + scheduletask['blueprint_draft'] = _.map(task['task_blueprints'], 'url'); + scheduletask['status'] = task['status']; + + //fetch task draft details + for(const key of commonkeys){ + scheduletask[key] = task[key]; + } + scheduletask['created_at'] = moment(task['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); + scheduletask['updated_at'] = moment(task['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); + scheduletask['specifications_doc'] = task['specifications_doc']; + scheduletask.duration = moment.utc((scheduletask.duration || 0)*1000).format('HH:mm:ss'); + scheduletask.relative_start_time = moment.utc(scheduletask.relative_start_time*1000).format('HH:mm:ss'); + scheduletask.relative_stop_time = moment.utc(scheduletask.relative_stop_time*1000).format('HH:mm:ss'); + scheduletask.template = task.specifications_template; + + for(const blueprint of task['task_blueprints']){ + let taskblueprint = []; + taskblueprint['tasktype'] = 'Blueprint'; + taskblueprint['actionpath'] = '/task/view/blueprint/'+blueprint['id']; + taskblueprint['blueprint_draft'] = blueprint['draft']; + taskblueprint['status'] = blueprint['status']; + + for(const key of commonkeys){ + taskblueprint[key] = blueprint[key]; + } + taskblueprint['created_at'] = moment(blueprint['created_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); + taskblueprint['updated_at'] = moment(blueprint['updated_at'], moment.ISO_8601).format("YYYY-MMM-DD HH:mm:ss"); + taskblueprint.duration = moment.utc((taskblueprint.duration || 0)*1000).format('HH:mm:ss'); + taskblueprint.relative_start_time = moment.utc(taskblueprint.relative_start_time*1000).format('HH:mm:ss'); + taskblueprint.relative_stop_time = moment.utc(taskblueprint.relative_stop_time*1000).format('HH:mm:ss'); + taskblueprint.template = scheduletask.template; + taskblueprint.subTasks = blueprint.subtasks; + for (const subtask of taskblueprint.subTasks) { + subtask.subTaskTemplate = _.find(this.subtaskTemplates, ['id', subtask.specifications_template_id]); + } + //Add Blue print details to array + scheduletasklist.push(taskblueprint); + } + //Add Task Draft details to array + scheduletasklist.push(scheduletask); + } + return scheduletasklist; + } + + /** + * Formatting the task_blueprints in blueprint view to pass to the ViewTable component + * @param {Object} schedulingUnit - scheduling_unit_blueprint object from extended API call loaded with tasks(blueprint) along with their template and subtasks + */ + getFormattedTaskBlueprints(schedulingUnit) { + let taskBlueprintsList = []; + for(const taskBlueprint of schedulingUnit.task_blueprints) { + taskBlueprint['tasktype'] = 'Blueprint'; + taskBlueprint['actionpath'] = '/task/view/blueprint/'+taskBlueprint['id']; + taskBlueprint['blueprint_draft'] = taskBlueprint['draft']; + taskBlueprint['relative_start_time'] = 0; + taskBlueprint['relative_stop_time'] = 0; + taskBlueprint.duration = moment.utc((taskBlueprint.duration || 0)*1000).format('HH:mm:ss'); + taskBlueprint.template = taskBlueprint.specifications_template; + for (const subtask of taskBlueprint.subtasks) { + subtask.subTaskTemplate = _.find(this.subtaskTemplates, ['id', subtask.specifications_template_id]); + } + taskBlueprint.subTasks = taskBlueprint.subtasks; + taskBlueprintsList.push(taskBlueprint); + } + return taskBlueprintsList; + } + getScheduleUnitTasks(type, scheduleunit){ if(type === 'draft') return ScheduleService.getTasksBySchedulingUnit(scheduleunit.id, true, true, true); @@ -268,13 +347,6 @@ class ViewSchedulingUnit extends Component{ </> } - {<Stations - stationGroup={this.state.stationGroup} - targetObservation={this.state.targetObservation} - view - />} - - {this.state.scheduleunit && this.state.scheduleunit.scheduling_constraints_doc && <SchedulingConstraint disable constraintTemplate={this.state.constraintSchema} initValue={this.state.scheduleunit.scheduling_constraints_doc} />} <div> <h3>Tasks Details</h3> </div> @@ -301,8 +373,16 @@ class ViewSchedulingUnit extends Component{ unittest={this.state.unittest} tablename="scheduleunit_task_list" /> - } - {this.state.showStatusLogs && + } + + {<Stations + stationGroup={this.state.stationGroup} + targetObservation={this.state.targetObservation} + view + />} + + {this.state.scheduleunit && this.state.scheduleunit.scheduling_constraints_doc && <SchedulingConstraint disable constraintTemplate={this.state.constraintSchema} initValue={this.state.scheduleunit.scheduling_constraints_doc} />} + {this.state.showStatusLogs && <Dialog header={`Status change logs - ${this.state.task?this.state.task.name:""}`} visible={this.state.showStatusLogs} maximizable maximized={false} position="left" style={{ width: '50vw' }} onHide={() => {this.setState({showStatusLogs: false})}}> diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js index 78f16a7deae9399dbb3f8c4968c2c56ff7417161..1878b35e09fd509d4577c28539b30a7716affe88 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js @@ -14,6 +14,7 @@ import ViewTable from '../../components/ViewTable'; import ProjectService from '../../services/project.service'; import ScheduleService from '../../services/schedule.service'; import UtilService from '../../services/util.service'; +import TaskService from '../../services/task.service'; import UnitConverter from '../../utils/unit.converter'; import SchedulingUnitSummary from '../Scheduling/summary'; @@ -89,14 +90,16 @@ export class TimelineView extends Component { async componentDidMount() { // Fetch all details from server and prepare data to pass to timeline and table components const promises = [ ProjectService.getProjectList(), - ScheduleService.getSchedulingUnitBlueprint(), + ScheduleService.getSchedulingUnitsExtended('blueprint'), ScheduleService.getSchedulingUnitDraft(), ScheduleService.getSchedulingSets(), UtilService.getUTC(), - ScheduleService.getStations('All')] ; + ScheduleService.getStations('All'), + TaskService.getSubtaskTemplates()] ; Promise.all(promises).then(async(responses) => { + this.subtaskTemplates = responses[6]; const projects = responses[0]; - const suBlueprints = _.sortBy(responses[1].data.results, 'name'); + const suBlueprints = _.sortBy(responses[1], 'name'); const suDrafts = responses[2].data.results; const suSets = responses[3]; const group = [], items = []; @@ -116,25 +119,29 @@ export class TimelineView extends Component { suBlueprint.suSet = suSet; suBlueprint.durationInSec = suBlueprint.duration; suBlueprint.duration = UnitConverter.getSecsToHHmmss(suBlueprint.duration); - // Load subtasks also to get stations & control ID from subtask if status is before scheduled - //const loadSubtasks = this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 || this.state.showTasks; - const loadSubtasks = true; + suBlueprint.tasks = suBlueprint.task_blueprints; // Select only blueprints with start_time and stop_time in the default time limit if (suBlueprint.start_time && (moment.utc(suBlueprint.start_time).isBetween(defaultStartTime, defaultEndTime) || - moment.utc(suBlueprint.stop_time).isBetween(defaultStartTime, defaultEndTime))) { - // suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true); - suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks); + moment.utc(suBlueprint.stop_time).isBetween(defaultStartTime, defaultEndTime)) + || (moment.utc(suBlueprint.start_time).isSameOrBefore(defaultStartTime) && + moment.utc(suBlueprint.stop_time).isSameOrAfter(defaultEndTime))) { items.push(this.getTimelineItem(suBlueprint)); if (!_.find(group, {'id': suDraft.id})) { group.push({'id': suDraft.id, title: suDraft.name}); } suList.push(suBlueprint); - } else if (suBlueprint.start_time) { // For other SUs with start_time load details asynchronously - ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks) - .then(tasks => { - suBlueprint.tasks = tasks; - }) + } + for (let task of suBlueprint.tasks) { + const subTaskIds = task.subtasks.filter(subtask => { + const template = _.find(this.subtaskTemplates, ['id', subtask.specifications_template_id]); + return (template && template.name.indexOf('control')) > 0; + }); + task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; + if (task.specifications_template.type_value.toLowerCase() === "observation") { + task.antenna_set = task.specifications_doc.antenna_set; + task.band = task.specifications_doc.filter; + } } } } @@ -155,6 +162,11 @@ export class TimelineView extends Component { } } }); + // Get all scheduling constraint templates + ScheduleService.getSchedulingConstraintTemplates() + .then(suConstraintTemplates => { + this.suConstraintTemplates = suConstraintTemplates; + }); this.setState({suBlueprints: suBlueprints, suDrafts: suDrafts, group: group, suSets: suSets, projects: projects, suBlueprintList: suList, items: items, currentUTC: currentUTC, isLoading: false, @@ -172,7 +184,7 @@ export class TimelineView extends Component { getTimelineItem(suBlueprint) { let antennaSet = ""; for (let task of suBlueprint.tasks) { - if (task.template.type_value.toLowerCase() === "observation") { + if (task.specifications_template.type_value.toLowerCase() === "observation") { antennaSet = task.specifications_doc.antenna_set; } } @@ -182,7 +194,7 @@ export class TimelineView extends Component { title: "", project: suBlueprint.project, type: 'SCHEDULE', name: suBlueprint.suDraft.name, - band: antennaSet.split("_")[0], + band: antennaSet?antennaSet.split("_")[0]:"", antennaSet: antennaSet, duration: suBlueprint.durationInSec?`${(suBlueprint.durationInSec/3600).toFixed(2)}Hrs`:"", start_time: moment.utc(suBlueprint.start_time), @@ -198,46 +210,54 @@ export class TimelineView extends Component { * Get Timeline items for obsercation tasks of the SU Bluprint. Task Items are grouped to the SU draft and Task draft IDs * @param {Object} suBlueprint */ - getTaskItems(suBlueprint) { + getTaskItems(suBlueprint, startTime, endTime) { let taskItems = {}; if (suBlueprint.tasks) { let items = [], itemGroup = []; + const subtaskTemplates = this.subtaskTemplates; for (let task of suBlueprint.tasks) { - if (task.template.type_value.toLowerCase() === "observation" && task.start_time && task.stop_time) { + if (task.specifications_template.type_value.toLowerCase() === "observation" && task.start_time && task.stop_time) { const antennaSet = task.specifications_doc.antenna_set; const start_time = moment.utc(task.start_time); const end_time = moment.utc(task.stop_time); - const subTaskIds = task.subTasks.filter(subtask => subtask.template.name.indexOf('control') > 0); - const controlId = subTaskIds.length>0 ? subTaskIds[0].id : ''; - let item = { id: `${suBlueprint.id}_${task.id}`, - suId: suBlueprint.id, - taskId: task.id, - controlId: controlId, - group: `${suBlueprint.suDraft.id}_${task.draft_id}`, - // group: `${suBlueprint.suDraft.id}_Tasks`, // For single row task grouping - title: '', - project: suBlueprint.project, type: 'TASK', - name: task.name, - typeValue:task.template.type_value, - band: antennaSet?antennaSet.split("_")[0]:"", - antennaSet: antennaSet?antennaSet:"", - duration: `${(end_time.diff(start_time, 'seconds')/3600).toFixed(2)}Hrs`, - start_time: start_time, - end_time: end_time, - bgColor: task.status? TASK_STATUS_COLORS[task.status.toUpperCase()]:"#2196f3", - selectedBgColor: "none", - status: task.status.toLowerCase()}; - items.push(item); - if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_${task.draft_id}`])) { - itemGroup.push({'id': `${suBlueprint.suDraft.id}_${task.draft_id}`, parent: suBlueprint.suDraft.id, - start: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- ${task.name}`}); - } - /* >>>>>> If all tasks should be shown in single row remove the above 2 lines and uncomment these lines - if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_Tasks`])) { - itemGroup.push({'id': `${suBlueprint.suDraft.id}_Tasks`, parent: suBlueprint.suDraft.id, - start_time: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- Tasks`}); + if ((start_time.isBetween(startTime, endTime) || + end_time.isBetween(startTime, endTime)) + || (start_time.isSameOrBefore(startTime) && end_time.isSameOrAfter(endTime))) { + const subTaskIds = task.subtasks.filter(subtask => { + const template = _.find(subtaskTemplates, ['id', subtask.specifications_template_id]); + return (template && template.name.indexOf('control')) > 0; + }); + const controlId = subTaskIds.length>0 ? subTaskIds[0].id : ''; + let item = { id: `${suBlueprint.id}_${task.id}`, + suId: suBlueprint.id, + taskId: task.id, + controlId: controlId, + group: `${suBlueprint.suDraft.id}_${task.draft_id}`, + // group: `${suBlueprint.suDraft.id}_Tasks`, // For single row task grouping + title: '', + project: suBlueprint.project, type: 'TASK', + name: task.name, + typeValue:task.specifications_template.type_value, + band: antennaSet?antennaSet.split("_")[0]:"", + antennaSet: antennaSet?antennaSet:"", + duration: `${(end_time.diff(start_time, 'seconds')/3600).toFixed(2)}Hrs`, + start_time: start_time, + end_time: end_time, + bgColor: task.status? TASK_STATUS_COLORS[task.status.toUpperCase()]:"#2196f3", + selectedBgColor: "none", + status: task.status.toLowerCase()}; + items.push(item); + if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_${task.draft_id}`])) { + itemGroup.push({'id': `${suBlueprint.suDraft.id}_${task.draft_id}`, parent: suBlueprint.suDraft.id, + start: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- ${task.name}`}); + } + /* >>>>>> If all tasks should be shown in single row remove the above 2 lines and uncomment these lines + if (!_.find(itemGroup, ['id', `${suBlueprint.suDraft.id}_Tasks`])) { + itemGroup.push({'id': `${suBlueprint.suDraft.id}_Tasks`, parent: suBlueprint.suDraft.id, + start_time: start_time, title: `${!this.state.showSUs?suBlueprint.suDraft.name:""} -- Tasks`}); + } + <<<<<<*/ } - <<<<<<*/ } } taskItems['items'] = items; @@ -273,18 +293,23 @@ export class TimelineView extends Component { canExtendSUList: false, canShrinkSUList:false}); if (fetchDetails) { const suBlueprint = _.find(this.state.suBlueprints, {id: (this.state.stationView?parseInt(item.id.split('-')[0]):item.id)}); + const suConstraintTemplate = _.find(this.suConstraintTemplates, {id: suBlueprint.suDraft.scheduling_constraints_template_id}); /* If tasks are not loaded on component mounting fetch from API */ if (suBlueprint.tasks) { - this.setState({suTaskList: _.sortBy(suBlueprint.tasks, "id"), - stationGroup: this.getSUStations(suBlueprint)}); + this.setState({suTaskList: _.sortBy(suBlueprint.tasks, "id"), suConstraintTemplate: suConstraintTemplate, + stationGroup: this.getSUStations(suBlueprint), isSummaryLoading: false}); } else { ScheduleService.getTaskBPWithSubtaskTemplateOfSU(suBlueprint) .then(taskList => { for (let task of taskList) { //Control Task Id - const subTaskIds = (task.subTasks || []).filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1); + // const subTaskIds = (task.subTasks || []).filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1); + const subTaskIds = task.subtasks.filter(subtask => { + const template = _.find(this.subtaskTemplates, ['id', subtask.specifications_template_id]); + return (template && template.name.indexOf('control')) > 0; + }); task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; - if (task.template.type_value.toLowerCase() === "observation") { + if (task.specifications_template.type_value.toLowerCase() === "observation") { task.antenna_set = task.specifications_doc.antenna_set; task.band = task.specifications_doc.filter; } @@ -294,10 +319,10 @@ export class TimelineView extends Component { }); } // Get the scheduling constraint template of the selected SU block - ScheduleService.getSchedulingConstraintTemplate(suBlueprint.suDraft.scheduling_constraints_template_id) - .then(suConstraintTemplate => { - this.setState({suConstraintTemplate: suConstraintTemplate, isSummaryLoading: false}); - }); + // ScheduleService.getSchedulingConstraintTemplate(suBlueprint.suDraft.scheduling_constraints_template_id) + // .then(suConstraintTemplate => { + // this.setState({suConstraintTemplate: suConstraintTemplate, isSummaryLoading: false}); + // }); } } } @@ -375,12 +400,12 @@ export class TimelineView extends Component { if (startTime && endTime) { for (const suBlueprint of this.state.suBlueprints) { if (moment.utc(suBlueprint.start_time).isBetween(startTime, endTime) - || moment.utc(suBlueprint.stop_time).isBetween(startTime, endTime)) { + || moment.utc(suBlueprint.stop_time).isBetween(startTime, endTime) + || (moment.utc(suBlueprint.start_time).isSameOrBefore(startTime) && + moment.utc(suBlueprint.stop_time).isSameOrAfter(endTime))) { // Get timeline item for station view noramlly and in timeline view only if SU to be shown let timelineItem = (this.state.showSUs || this.state.stationView)?this.getTimelineItem(suBlueprint):null; if (this.state.stationView) { - const loadSubtasks = (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 || this.state.showTasks); - suBlueprint.tasks = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true, loadSubtasks, loadSubtasks); this.getStationItemGroups(suBlueprint, timelineItem, this.allStationsGroup, items); } else { // Add timeline SU item @@ -394,7 +419,7 @@ export class TimelineView extends Component { } // Add task item only in timeline view and when show task is enabled if (this.state.showTasks && !this.state.stationView) { - const taskItems = this.getTaskItems(suBlueprint); + const taskItems = this.getTaskItems(suBlueprint, startTime, endTime); items = items.concat(taskItems.items); group = group.concat(taskItems.group); } @@ -446,7 +471,7 @@ export class TimelineView extends Component { getSUStations(suBlueprint) { let stations = []; /* Get all observation tasks */ - const observationTasks = _.filter(suBlueprint.tasks, (task) => { return task.template.type_value.toLowerCase() === "observation"}); + const observationTasks = _.filter(suBlueprint.tasks, (task) => { return task.specifications_template.type_value.toLowerCase() === "observation"}); for (const observationTask of observationTasks) { /** If the status of SU is before scheduled, get all stations from the station_groups from the task specification_docs */ if (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) >= 0 @@ -455,9 +480,9 @@ export class TimelineView extends Component { stations = _.concat(stations, grpStations); } } else if (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 - && observationTask.subTasks) { + && observationTask.subtasks) { /** If the status of SU is scheduled or after get the stations from the subtask specification tasks */ - for (const subtask of observationTask.subTasks) { + for (const subtask of observationTask.subtasks) { if (subtask.specifications_doc.stations) { stations = _.concat(stations, subtask.specifications_doc.stations.station_list); } @@ -477,9 +502,16 @@ export class TimelineView extends Component { let reservations = this.reservations; for (const reservation of reservations) { const reservationStartTime = moment.utc(reservation.start_time); + const reservationEndTime = reservation.duration?reservationStartTime.clone().add(reservation.duration, 'seconds'):endTime; const reservationSpec = reservation.specifications_doc; - if ( (reservationStartTime.isSameOrAfter(startTime) - || reservationStartTime.isSameOrBefore(endTime)) + if ( (reservationStartTime.isSame(startTime) + || reservationStartTime.isSame(endTime) + || reservationStartTime.isBetween(startTime, endTime) + || reservationEndTime.isSame(startTime) + || reservationEndTime.isSame(endTime) + || reservationEndTime.isBetween(startTime, endTime) + || (reservationStartTime.isSameOrBefore(startTime) + && reservationEndTime.isSameOrAfter(endTime))) && (!this.state.reservationFilter || // No reservation filter added reservationSpec.activity.type === this.state.reservationFilter) ) { // Reservation reason == Filtered reaseon if (reservationSpec.resources.stations) { @@ -591,7 +623,7 @@ export class TimelineView extends Component { } } if (this.state.showTasks && !this.state.stationView) { - const taskItems = this.getTaskItems(suBlueprint); + const taskItems = this.getTaskItems(suBlueprint, this.state.currentStartTime, this.state.currentEndTime); items = items.concat(taskItems.items); group = group.concat(taskItems.group); } diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js index 8cbd0d9aab0d69adbec3ec49373919ba5628eee1..d4bd21174398b2521f18853c2821cb3790f2af83 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/week.view.js @@ -14,6 +14,7 @@ import ViewTable from '../../components/ViewTable'; import ProjectService from '../../services/project.service'; import ScheduleService from '../../services/schedule.service'; import UtilService from '../../services/util.service'; +import TaskService from '../../services/task.service'; import UnitConverter from '../../utils/unit.converter'; import SchedulingUnitSummary from '../Scheduling/summary'; @@ -69,19 +70,19 @@ export class WeekTimelineView extends Component { async componentDidMount() { // Fetch all details from server and prepare data to pass to timeline and table components const promises = [ ProjectService.getProjectList(), - ScheduleService.getSchedulingUnitBlueprint(), + ScheduleService.getSchedulingUnitsExtended('blueprint'), ScheduleService.getSchedulingUnitDraft(), ScheduleService.getSchedulingSets(), - UtilService.getUTC()] ; + UtilService.getUTC(), + TaskService.getSubtaskTemplates()] ; Promise.all(promises).then(async(responses) => { + this.subtaskTemplates = responses[5]; const projects = responses[0]; - const suBlueprints = _.sortBy(responses[1].data.results, 'name'); + const suBlueprints = _.sortBy(responses[1], 'name'); const suDrafts = responses[2].data.results; const suSets = responses[3] const group = [], items = []; const currentUTC = moment.utc(responses[4]); - // const defaultStartTime = currentUTC.clone().add(-24, 'hours'); // Default start time, this should be updated if default view is changed. - // const defaultEndTime = currentUTC.clone().add(24, 'hours'); // Default end time, this should be updated if default view is changed. const defaultStartTime = moment.utc().day(-2).hour(0).minutes(0).seconds(0); const defaultEndTime = moment.utc().day(8).hour(23).minutes(59).seconds(59); for (const count of _.range(11)) { @@ -101,10 +102,13 @@ export class WeekTimelineView extends Component { suBlueprint.suSet = suSet; suBlueprint.durationInSec = suBlueprint.duration; suBlueprint.duration = UnitConverter.getSecsToHHmmss(suBlueprint.duration); + suBlueprint.tasks = suBlueprint.task_blueprints; // Select only blueprints with start_time and stop_time in the default time limit if (suBlueprint.start_time && (moment.utc(suBlueprint.start_time).isBetween(defaultStartTime, defaultEndTime) || - moment.utc(suBlueprint.stop_time).isBetween(defaultStartTime, defaultEndTime))) { + moment.utc(suBlueprint.stop_time).isBetween(defaultStartTime, defaultEndTime)) + || (moment.utc(suBlueprint.start_time).isSameOrBefore(defaultStartTime, defaultEndTime) && + moment.utc(suBlueprint.stop_time).isSameOrAfter(defaultStartTime, defaultEndTime))) { const startTime = moment.utc(suBlueprint.start_time); const endTime = moment.utc(suBlueprint.stop_time); @@ -121,75 +125,63 @@ export class WeekTimelineView extends Component { } suList.push(suBlueprint); } + // Add Subtask Id as control id for task if subtask type us control. Also add antenna_set & band prpoerties to the task object. + for (let task of suBlueprint.tasks) { + const subTaskIds = task.subtasks.filter(subtask => { + const template = _.find(this.subtaskTemplates, ['id', subtask.specifications_template_id]); + return (template && template.name.indexOf('control')) > 0; + }); + task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; + if (task.specifications_template.type_value.toLowerCase() === "observation") { + task.antenna_set = task.specifications_doc.antenna_set; + task.band = task.specifications_doc.filter; + } + } + // Get stations involved for this SUB + let stations = this.getSUStations(suBlueprint); + suBlueprint.stations = _.uniq(stations); } } } - + // Get all scheduling constraint templates + ScheduleService.getSchedulingConstraintTemplates() + .then(suConstraintTemplates => { + this.suConstraintTemplates = suConstraintTemplates; + }); this.setState({suBlueprints: suBlueprints, suDrafts: suDrafts, group: _.sortBy(group, ['value']), suSets: suSets, projects: projects, suBlueprintList: suList, items: items, currentUTC: currentUTC, isLoading: false, startTime: defaultStartTime, endTime: defaultEndTime }); - // Load SU tasks asynchronously for SUs - this.loadSUTasks(); }); - // Get maingroup and its stations + // Get maingroup and its stations. This grouping is used to show count of stations used against each group. ScheduleService.getMainGroupStations() .then(stationGroups => {this.mainStationGroups = stationGroups}); } - /** - * Loads tasks, subtasks, templates and stations of the Scheduling Units - */ - loadSUTasks() { - let suBlueprints = this.state.suBlueprints; - for (let suBlueprint of suBlueprints) { - ScheduleService.getTaskBPWithSubtaskTemplateOfSU(suBlueprint) - .then(taskList => { - for (let task of taskList) { - //Control Task ID - const subTaskIds = (task.subTasks || []).filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1); - task.subTaskID = subTaskIds.length ? subTaskIds[0].id : ''; - if (task.template.type_value.toLowerCase() === "observation") { - task.antenna_set = task.specifications_doc.antenna_set; - task.band = task.specifications_doc.filter; - } - } - suBlueprint.tasks = taskList; - let stations = this.getSUStations(suBlueprint); - suBlueprint.stations = _.uniq(stations); - }); - } - this.setState({suBlueprints: suBlueprints}); - } - /** * Function to get/prepare Item object to be passed to Timeline component * @param {Object} suBlueprint */ async getTimelineItem(suBlueprint, displayDate) { let antennaSet = ""; - const taskList = await ScheduleService.getTaskBlueprintsBySchedulingUnit(suBlueprint, true); - for (let task of taskList) { - if (task.template.type_value.toLowerCase() === "observation") { + for (let task of suBlueprint.tasks) { + if (task.specifications_template.type_value.toLowerCase() === "observation") { antennaSet = task.specifications_doc.antenna_set; } } let item = { id: `${suBlueprint.id}-${suBlueprint.start_time}`, suId: suBlueprint.id, - // group: suBlueprint.suDraft.id, group: moment.utc(suBlueprint.start_time).format("MMM DD ddd"), - // title: `${suBlueprint.project} - ${(suBlueprint.durationInSec/3600).toFixed(2)}Hrs - ${antennaSet}`, title: "", project: suBlueprint.project, name: suBlueprint.suDraft.name, - band: antennaSet.split("_")[0], + band: antennaSet?antennaSet.split("_")[0]:"", antennaSet: antennaSet, duration: suBlueprint.durationInSec?`${(suBlueprint.durationInSec/3600).toFixed(2)}Hrs`:"", start_time: moment.utc(`${displayDate.format('YYYY-MM-DD')} ${suBlueprint.start_time.split('T')[1]}`), end_time: moment.utc(`${displayDate.format('YYYY-MM-DD')} ${suBlueprint.stop_time.split('T')[1]}`), bgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3", - // selectedBgColor: suBlueprint.status? STATUS_COLORS[suBlueprint.status.toUpperCase()]:"#2196f3"} selectedBgColor: 'none', type: 'SCHEDULE', status: suBlueprint.status.toLowerCase()}; @@ -211,14 +203,14 @@ export class WeekTimelineView extends Component { canExtendSUList: false, canShrinkSUList:false}); if (fetchDetails) { const suBlueprint = _.find(this.state.suBlueprints, {id: parseInt(item.id.split('-')[0])}); + const suConstraintTemplate = _.find(this.suConstraintTemplates, {id: suBlueprint.suDraft.scheduling_constraints_template_id}); /* If tasks are not loaded on component mounting fetch from API */ if (suBlueprint.tasks) { - this.setState({suTaskList: _.sortBy(suBlueprint.tasks, "id"), - stationGroup: suBlueprint.stations}) + this.setState({suTaskList: _.sortBy(suBlueprint.tasks, "id"), suConstraintTemplate: suConstraintTemplate, + stationGroup: suBlueprint.stations, isSummaryLoading: false}) } else { ScheduleService.getTaskBPWithSubtaskTemplateOfSU(suBlueprint) .then(taskList => { - const observationTask = _.find(taskList, (task)=> {return task.template.type_value==='observation' && task.specifications_doc.station_groups}); for (let task of taskList) { //Control Task ID const subTaskIds = (task.subTasks || []).filter(sTask => sTask.subTaskTemplate.name.indexOf('control') > 1); @@ -233,10 +225,10 @@ export class WeekTimelineView extends Component { }); } // Get the scheduling constraint template of the selected SU block - ScheduleService.getSchedulingConstraintTemplate(suBlueprint.suDraft.scheduling_constraints_template_id) - .then(suConstraintTemplate => { - this.setState({suConstraintTemplate: suConstraintTemplate, isSummaryLoading: false}); - }); + // ScheduleService.getSchedulingConstraintTemplate(suBlueprint.suDraft.scheduling_constraints_template_id) + // .then(suConstraintTemplate => { + // this.setState({suConstraintTemplate: suConstraintTemplate, isSummaryLoading: false}); + // }); } } } @@ -301,7 +293,7 @@ export class WeekTimelineView extends Component { getSUStations(suBlueprint) { let stations = []; /* Get all observation tasks */ - const observationTasks = _.filter(suBlueprint.tasks, (task) => { return task.template.type_value.toLowerCase() === "observation"}); + const observationTasks = _.filter(suBlueprint.tasks, (task) => { return task.specifications_template.type_value.toLowerCase() === "observation"}); for (const observationTask of observationTasks) { /** If the status of SU is before scheduled, get all stations from the station_groups from the task specification_docs */ if (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) >= 0 @@ -310,9 +302,9 @@ export class WeekTimelineView extends Component { stations = _.concat(stations, grpStations); } } else if (this.STATUS_BEFORE_SCHEDULED.indexOf(suBlueprint.status.toLowerCase()) < 0 - && observationTask.subTasks) { + && observationTask.subtasks) { /** If the status of SU is scheduled or after get the stations from the subtask specification tasks */ - for (const subtask of observationTask.subTasks) { + for (const subtask of observationTask.subtasks) { if (subtask.specifications_doc.stations) { stations = _.concat(stations, subtask.specifications_doc.stations.station_list); } @@ -340,7 +332,9 @@ export class WeekTimelineView extends Component { if (startTime && endTime) { for (const suBlueprint of this.state.suBlueprints) { if (moment.utc(suBlueprint.start_time).isBetween(startTime, endTime) - || moment.utc(suBlueprint.stop_time).isBetween(startTime, endTime)) { + || moment.utc(suBlueprint.stop_time).isBetween(startTime, endTime) + || (moment.utc(suBlueprint.start_time).isSameOrBefore(startTime, endTime) && + moment.utc(suBlueprint.stop_time).isSameOrAfter(startTime, endTime))) { suBlueprintList.push(suBlueprint); const suStartTime = moment.utc(suBlueprint.start_time); const suEndTime = moment.utc(suBlueprint.stop_time); diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js index edc85678a25726799c443d2f67d9a59333fce0fc..9d1170a385261d0a2f82be412e4cb718ab0fc48b 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js @@ -30,6 +30,43 @@ const ScheduleService = { } return res; }, + getSchedulingUnitsExtended: async function (type){ + let blueprints = []; + try { + let initialResponse = await axios.get(`/api/scheduling_unit_${type}_extended`); + const totalCount = initialResponse.data.count; + const initialCount = initialResponse.data.results.length + blueprints = blueprints.concat(initialResponse.data.results); + if (totalCount > initialCount) { + let secondResponse = await axios.get(`/api/scheduling_unit_${type}_extended/?ordering=id&limit=${totalCount-initialCount}&offset=${initialCount}`); + blueprints = blueprints.concat(secondResponse.data.results); + } + } catch(error) { + console.error('[schedule.services.getSchedulingUnitsExtended]',error); + } + return blueprints; + }, + getSchedulingUnitExtended: async function (type, id){ + let schedulingUnit = null; + try { + const response = await axios.get(`/api/scheduling_unit_${type}_extended/${id}/`); + schedulingUnit = response.data; + if (schedulingUnit) { + if (type === "blueprint") { + const schedulingUnitDraft = (await axios.get(`/api/scheduling_unit_draft/${id}/`)).data; + schedulingUnit.draft_object = schedulingUnitDraft; + schedulingUnit.scheduling_set_id = schedulingUnitDraft.scheduling_set_id; + schedulingUnit.scheduling_constraints_doc = schedulingUnitDraft.scheduling_constraints_doc; + } + const schedulingSet = (await axios.get(`/api/scheduling_set/${schedulingUnit.scheduling_set_id}`)).data; + schedulingUnit.scheduling_set_object = schedulingSet; + schedulingUnit.scheduling_set = schedulingSet.url; + } + } catch(error) { + console.error('[schedule.services.getSchedulingUnitExtended]',error); + } + return schedulingUnit; + }, //>>>>>> TODO: Remove this method by using/modifying other functions with additional parameters getTaskBPWithSubtaskTemplate: async function(id) { let result; diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js index 34a1e75b3d052010bf1deb74540d3c7761835ae4..997c5635b66e54d96b211d03014c48f1bae29cb4 100644 --- a/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js +++ b/SAS/TMSS/frontend/tmss_webapp/src/services/task.service.js @@ -186,6 +186,14 @@ const TaskService = { } return statusLogs; }, + getSubtaskTemplates: async function(templateId) { + try { + const response = await axios.get(`/api/subtask_template/`); + return response.data.results; + } catch(error) { + console.error(error); + } + }, getSubtaskTemplate: async function(templateId) { try { const response = await axios.get(`/api/subtask_template/${templateId}`); diff --git a/SAS/TMSS/services/feedback_handling/lib/feedback_handling.py b/SAS/TMSS/services/feedback_handling/lib/feedback_handling.py index 296c3705322b807d3063c002ad791771221845a1..ebf4821abd5a70f0228138cd08bfc56727703612 100644 --- a/SAS/TMSS/services/feedback_handling/lib/feedback_handling.py +++ b/SAS/TMSS/services/feedback_handling/lib/feedback_handling.py @@ -70,12 +70,25 @@ class TMSSFeedbackListener: try: # get message from messagebus msg = fbus.get(1) - # add contained feedback to TMSS - self.append_feedback_to_tmss_subtask_raw_feedback(msg.momid, msg.payload) - # try processing it, which will will fail until feedback of the subtask is complete. - self.process_subtask_feedback_and_set_finished(msg.momid) + + if msg is not None: + # note: cobalt/rtcp creates feedback and assumes that the observationID has its origin in OTDB. + # hence, it stores this id in the 'sasid' property of the message. + # We know that TMSS sets its subtask_id in the parset in the Observation.ObsID field, + # so we can fetch the TMSS subtask_id from the msg's sasid. + tmss_subtask_id = msg.sasid + + logger.info("received feedback from bus='%s' for TMSS subtask id=%s payload=%s", ex, tmss_subtask_id, msg.payload) + + # add contained feedback to TMSS + self.append_feedback_to_tmss_subtask_raw_feedback(tmss_subtask_id, msg.payload) + + # try processing it, which will will fail until feedback of the subtask is complete. + self.process_subtask_feedback_and_set_finished(tmss_subtask_id) except TimeoutError: pass + except Exception as e: + logger.error(str(e)) logger.info('Stopped listening on exchange=%s broker=%s' % (ex, broker_feedback)) for exchange in self.exchanges: @@ -90,6 +103,8 @@ class TMSSFeedbackListener: thread.join(5) def main(): + logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', level=logging.INFO) + from lofar.common.util import waitForInterrupt with TMSSFeedbackListener(): waitForInterrupt() diff --git a/SAS/TMSS/services/scheduling/lib/dynamic_scheduling.py b/SAS/TMSS/services/scheduling/lib/dynamic_scheduling.py index 65effc03349d8a05de3b3c85e1dcb6fafbab0eb4..727a8a935c1b3105e710f479ac551a274a25404a 100644 --- a/SAS/TMSS/services/scheduling/lib/dynamic_scheduling.py +++ b/SAS/TMSS/services/scheduling/lib/dynamic_scheduling.py @@ -41,6 +41,7 @@ from lofar.sas.tmss.services.scheduling.constraints import * # LOFAR needs to have a gap in between observations to (re)initialize hardware. DEFAULT_INTER_OBSERVATION_GAP = timedelta(seconds=60) +DEFAULT_NEXT_STARTTIME_GAP = timedelta(seconds=180) ################## core dynamic scheduling methods ################################################ # # @@ -82,7 +83,7 @@ def schedule_next_scheduling_unit() -> models.SchedulingUnitBlueprint: schedulable_units = get_schedulable_scheduling_units() # estimate the lower_bound_start_time - lower_bound_start_time = get_min_earliest_possible_start_time(schedulable_units, datetime.utcnow()) + lower_bound_start_time = get_min_earliest_possible_start_time(schedulable_units, datetime.utcnow()+DEFAULT_NEXT_STARTTIME_GAP) # estimate the upper_bound_stop_time, which may give us a small timewindow before any next scheduled unit, or a default window of a day try: diff --git a/SAS/TMSS/test/test_utils.py b/SAS/TMSS/test/test_utils.py index c24b714b8f8a4d9bf56aa7dddb26047787919fbd..77e8f309e99d0972fb9061f3294edbe5d27123cc 100644 --- a/SAS/TMSS/test/test_utils.py +++ b/SAS/TMSS/test/test_utils.py @@ -376,11 +376,8 @@ class TMSSTestEnvironment: if self._start_dynamic_scheduler: from lofar.sas.tmss.services.scheduling.dynamic_scheduling import create_dynamic_scheduling_service, models - # by default, dynamic scheduling is disabled in TMSS. - # In this test environment, we do want to have it enabled. Why else would we wanna start this service? - setting = models.Setting.objects.get(name=models.Flag.Choices.DYNAMIC_SCHEDULING_ENABLED.value) - setting.value = True - setting.save() + # beware: by default, dynamic scheduling is disabled in TMSS. + # so, even if we start the service, even then the dynamic scheduling is disable in the settings. self.dynamic_scheduler = create_dynamic_scheduling_service(exchange=self._exchange, broker=self._broker) self.dynamic_scheduler.start_listening()