Suggest: Times to schedule a job

Optimize resources, schedule, and dispatch a job using the optimize/suggest endpoint and GraphQL

The Suggest scheduling optimization feature proposes time/s to schedule a single job with a set of resources during a specified time range. This can be particularly useful for jobs that have specified time constraints (see Job time constraints for more information).

The /planr/optimize/suggest REST API endpoint requires the following fields in the request body:

Field Description Type
suggestForNode The UID of the job to be scheduled. String
resourceIds The UID/s of the available resources. You can include multiple resources in the Suggest query, with the UID for each resource separated with a comma. Array of IDs
scheduleStart Can be either ISO8601 date time string or Unix timestamp number ( in milliseconds ). Indicates the start of the time range to consider for job scheduling. String
scheduleEnd Can be either ISO8601 date time string or Unix timestamp number ( in milliseconds ). Indicates the end time of the job scheduling window. String

You can also specify schedulingOptions to add further constraints to your query. The following schedulingOptions are available:

Field Description Type Default
jobTimeAsTimeConstraint When a job has a time set, consider it to be a time constraint and never reschedule to another time slot. Boolean true
preferJobTimeOverTimeConstraint When a job with a JobTimeConstraint also has a time set, consider the job time as the authoritative constraint and ignore the JobTimeConstraint. Boolean true
respectSchedule For a job that is allocated and in “Pending Dispatch” status, do not move the job to a different time. Boolean true
ignoreTravelTimes Ignore all travel times between resources and jobs. Boolean false
ignoreTravelTimeFirstJob Ignore travel time from a resource’ home location to the first job. Boolean false
ignoreTravelTimeLastJob Ignore travel time to the resource’ home location from the last job. Boolean false
padding A fixed interval of time between consecutive jobs. Integer 0
snapUnit Divide the given time frame into parts described by this value and allocate all jobs to the nearest part in seconds. Integer 0 (>=0)

Example: Suggest a time for a job, assign, and dispatch using REST and GraphQL

In the following example, we will use GraphQL and the /optimize/suggest REST API to find the best time to schedule a job. We will then update the job using GraphQL and dispatch it to the resource using the /notifications/dispatch endpoint.

The job we want to schedule is has a 60 minute duration, it must be completed on Monday, we have four resources, and they already have jobs scheduled throughout that day:

Jobs already scheduled with four resources.
  1. Run a GraphQL query to obtain the UID for each of your resources in the region where you want to schedule the job. In our example, we are scheduling a job in Brisbane, Australia:

    query fetchRegions {
      regions(filter: "UID == '00036206-7555-4280-b1b7-86d566437391'") {
        edges {
          node {
            UID
            Name
            Resources {
              Name
              UID
            }
          }
        }
      }
    }
    

    This query returns the Name and UID of all four resources in the region:

    {
      "data": {
        "regions": {
          "edges": [
            {
              "node": {
                "UID": "00036206-7555-4280-b1b7-86d566437391",
                "Name": "Brisbane",
                "Resources": [
                  {
                    "Name": "David Kimi",
                    "UID": "000520bd-63a1-47a0-9c80-9a343cb35ec6"
                  },
                  {
                    "Name": "John Smith",
                    "UID": "0005a7e9-b1aa-44da-937f-310b921b75cc"
                  },
                  {
                    "Name": "Leia Organa",
                    "UID": "0005a97d-9535-411f-be39-61a2fad9683b"
                  },
                  {
                    "Name": "Mary Brown",
                    "UID": "000521e3-b4ab-417e-8fc2-23647246b085"
                  }
                ]
              }
            }
          ]
        }
      }
    }
    
  2. Send a POST request to the /planr/optimize/suggest endpoint to find what times your resources are available to complete the job during the required scheduling window.

    The example request body includes the following information:

    • The resourceIds of our four resources.
    • The scheduleStart and scheduleEnd of the scheduling window in ISO 8601 format.
    • We’ve allowed 5 minutes of padding between jobs.
    • All other scheduling options are default.
    {
    	"suggestForNode": "00149a7b-22a5-463c-ab33-c1696ca49a10",
    	"resourceIds": [
    		"000520bd-63a1-47a0-9c80-9a343cb35ec6","0005a7e9-b1aa-44da-937f-310b921b75cc", "0005a97d-9535-411f-be39-61a2fad9683b","000521e3-b4ab-417e-8fc2-23647246b085"
    	],
      "scheduleStart": "2022-07-04T08:30:00+10:00",
      "scheduleEnd": "2022-07-04T17:00:00+10:00",
    	"schedulingOptions": {
    		"jobTimeAsTimeConstraint": true,
    		"preferJobTimeOverTimeConstraint": true,
    		"respectSchedule": true,
    		"ignoreTravelTimes": false,
    		"ignoreTravelTimeFirstJob": false,
    		"ignoreTravelTimeLastJob": false,
    		"padding": 5,
    		"snapUnit": 0
    	}
    }
    

    The response returns the following result:

    {
    	"result": {
    		"routes": {
    			"0005a97d-9535-411f-be39-61a2fad9683b": {
    				"resourceId": "0005a97d-9535-411f-be39-61a2fad9683b",
    				"score": {
    					"hard": 0,
    					"medium": 0,
    					"soft": -60
    				},
    				"route": {
    					"jobId": "00149a7b-22a5-463c-ab33-c1696ca49a10",
    					"jobName": "JOB-0104",
    					"start": "2022-07-04T00:54:00.000Z",
    					"duration": 60,
    					"travelTime": 14,
    					"type": "job"
    				},
    				"gapList": [
    					{
    						"fromPrev": {
    							"travelTime": 14
    						},
    						"interval": {
    							"start": "2022-07-04T00:54:00.000Z",
    							"end": "2022-07-04T01:54:00.000Z"
    						},
    						"toNext": {
    							"travelTime": 0
    						}
    					}
    				],
    				"isAllocated": false
    			},
    			"000521e3-b4ab-417e-8fc2-23647246b085": {
    				"resourceId": "000521e3-b4ab-417e-8fc2-23647246b085",
    				"score": {
    					"hard": 0,
    					"medium": 0,
    					"soft": -131
    				},
    				"route": {
    					"jobId": "00149a7b-22a5-463c-ab33-c1696ca49a10",
    					"jobName": "JOB-0104",
    					"start": "2022-07-04T01:39:00.000Z",
    					"duration": 60,
    					"travelTime": 23,
    					"type": "job"
    				},
    				"gapList": [
    					{
    						"fromPrev": {
    							"travelTime": 23
    						},
    						"interval": {
    							"start": "2022-07-04T01:39:00.000Z",
    							"end": "2022-07-04T02:39:00.000Z"
    						},
    						"toNext": {
    							"travelTime": 0
    						}
    					}
    				],
    				"isAllocated": false
    			}
    		}
    	}
    }
    

    From the result, we can see that there are two resources available on Monday that can complete the job. The results are shown in order of who can complete the job first.

  3. Allocate one of the resources to the job update the start and end times using a GraphQL query.

    In this example, we are going to assign the job to the first resource returned in the /optimize/suggest query, schedule, and dispatch it using GraphQL:

    mutation saveSuggestResult {
          schema {
            updateJobs(input: {
              UID: "00149a7b-22a5-463c-ab33-c1696ca49a10"
              Start:"2022-07-04T00:54:00.000Z"
              End: "2022-07-04T01:54:00.000Z"
              Duration: 60
            })
            insertJobAllocations(input: {
              JobId: "00149a7b-22a5-463c-ab33-c1696ca49a10"
              ResourceId: "0005a97d-9535-411f-be39-61a2fad9683b"
              Status: "Dispatched"
            })
          }
        }
    

    The result indicates that the updateJobs request to schedule the job and the insertJobAllocations request to assign the job to a resource and dispatch it were both successful:

    {
      "data": {
        "schema": {
          "updateJobs": "00149a7b-22a5-463c-ab33-c1696ca49a10",
          "insertJobAllocations": "0018715f-f728-410f-811c-ffcdd589cc26"
        }
      }
    }
    
  4. Open the job in the swimlane to see that it has been scheduled and dispatched:

    Suggest job scheduled and dispatched.