Managing Jobs

This section explains how to use the Connect Server APIs to obtain details about your existing content jobs and register job kill orders.

This section is only for jobs associated with existing content. See the Deploying Content section for help creating and deploying content, and the Managing Content section for help discovering and managing existing content.

Note

We use the CONNECT_SERVER and CONNECT_API_KEY environment variables introduced in the Getting Started section of this cookbook.

Find a job and register a kill order

The following snippets search for a piece of content, identify a job, and register a job kill order.

Workflow

There are five steps if you need to find the content guid first. If you already know the content guid, then start with step 3.

  1. Search for a piece of content by name/owner via the GET /v1/content endpoint.
  2. Note the guid for the desired content.
  3. Retrieve all jobs associated with the piece of content via the GET /v1/content/{guid}/jobs endpoint.
  4. Note the key for the specific job that is desired to be killed.
  5. Register a job kill order for the desired job via the DELETE /v1/content/{guid}/jobs/{key} endpoint.

Search for a content item

First, search for a piece of content by name/owner via the GET /v1/content endpoint. See the List Content Items section for instructions on how to search for particular content items by using the name and/or the owner of the content using the name and owner_guid request parameters.

Once you have identified the content item with an associated job you desire to kill, note the guid value which will be used in the next section to query jobs.

Note

Alternatively, the content guid can be found in the Connect UI within the Info pane for a piece of content.

**Info** pane button and content guid.

Search for a job key

Using the guid value for a content item from the previous section, retrieve all jobs associated via the GET /v1/content/{guid}/jobs request. A request to this endpoint returns all jobs for the content item, even jobs that have ended. To see only currently running jobs, filter only the entries with exit_code set to null, which the code samples below include.

Alternatively, the job key can also be found in the content logs, which are visible in the Connect UI for a piece of content by clicking the Show Logs button.

**Show Logs** button.

The job key is displayed at the beginning of the second line.

Job key

Sample code

export CONTENT_GUID="d1873f6a-6b1c-42b7-a299-4d332291b0d5"

ALL_JOBS=$(curl --silent --show-error -L --max-redirs 0 --fail \
    -X GET \
    -H "Authorization: Key ${CONNECT_API_KEY}" \
    "${CONNECT_SERVER}__api__/v1/content/${CONTENT_GUID}/jobs")
echo "${ALL_JOBS}" | jq -r '.[] | select(.exit_code == null)'
import requests
import os

connect_server = os.environ.get('CONNECT_SERVER')
connect_api_key = os.environ.get('CONNECT_API_KEY')

# The 'guid' value comes from an earlier /content search.
guid = "d1873f6a-6b1c-42b7-a299-4d332291b0d5"

full_url = f"{connect_server}__api__/v1/content/{guid}/jobs"
headers = { 'Authorization': 'Key ' + connect_api_key }

response = requests.get(full_url, headers=headers)
response_current = [x for x in response.json() if x['exit_code'] == None]

print(response_current)
library(httr)

# The CONNECT_SERVER URL must have a trailing slash.
connectServer <- Sys.getenv("CONNECT_SERVER")
connectAPIKey <- Sys.getenv("CONNECT_API_KEY")

# The 'guid' value comes from an earlier /content search.
guid <- "d1873f6a-6b1c-42b7-a299-4d332291b0d5"

response <- GET(
    paste0(connectServer, "__api__/v1/content/", guid, "/jobs"),
    add_headers(Authorization = paste("Key", connectAPIKey))
)
  
# print only jobs which have an exit_code of NULL
print(content(response)[unlist(lapply(content(response), function(x) is.null(x$exit_code)))])

Sample response

# => [
# =>   {
# =>     "id": "28138918",
# =>     "ppid": null,
# =>     "pid": "0",
# =>     "key": "thP5sQmLPRlSqLUG",
# =>     ...
# =>     "start_time": "2022-11-21T16:36:15Z",
# =>     "end_time": "2022-11-21T16:38:21Z",
# =>     "last_heartbeat_time": "2022-11-21T16:38:19Z",
# =>     ...
# =>   },
# =>   {
# =>     "id": "28138916",
# =>     "ppid": null,
# =>     "pid": "0",
# =>     "key": "jDofwjlIUrzR4e4H",
# =>     ...
# =>     "start_time": "2022-11-21T16:36:07Z",
# =>     "end_time": "2022-11-21T16:36:14Z",
# =>     "last_heartbeat_time": "2022-11-21T16:36:12Z",
# =>     ...
# =>   }
# => ]

Once you have identified the specific job you desire to kill, note the key value which is used in the next section to register a kill request.

Register a job kill order

Using the guid value for a content item and the key value for a specific job from the previous sections, register a job kill order for the desired job via the DELETE /v1/content/{guid}/jobs/{key} request.

Sample code

export CONTENT_GUID="2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
export JOB_KEY="z5nLrqPamgi2NHpb"

curl --silent --show-error -L --max-redirs 0 --fail \
    -X DELETE \
    -H "Authorization: Key ${CONNECT_API_KEY}" \
    "${CONNECT_SERVER}__api__/v1/content/${CONTENT_GUID}/jobs/${JOB_KEY}"
import requests
import os

connect_server = os.environ.get('CONNECT_SERVER')
connect_api_key = os.environ.get('CONNECT_API_KEY')

# The 'guid' value comes from an earlier /content search.
guid = "2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
# The 'key' value comes from the /content/guid/jobs search.
key = "z5nLrqPamgi2NHpb"

full_url = f"{connect_server}__api__/v1/content/{guid}/jobs/{key}"
headers = { 'Authorization': 'Key ' + connect_api_key }

response = requests.delete(full_url, headers=headers)

print(response.json())
library(httr)

# The CONNECT_SERVER URL must have a trailing slash.
connectServer <- Sys.getenv("CONNECT_SERVER")
connectAPIKey <- Sys.getenv("CONNECT_API_KEY")

# The 'guid' value comes from an earlier /content search.
guid <- "2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
# The 'key' value comes from the /content/{guid}/jobs search.
key <- "z5nLrqPamgi2NHpb"

response <- DELETE(
    paste0(connectServer, "__api__/v1/content/", guid, "/jobs/", key),
    add_headers(Authorization = paste("Key", connectAPIKey))
)

print(content(response))

Sample response

# => {
# =>   "guid": "e43852e8-eb93-4f50-bfb9-46d04044e28b",
# =>   "app_id": 13872,
# =>   "app_guid": "2106c1b1-5cec-40df-a014-4ced0a4c3ccd",
# =>   "job_id": 28148421,
# =>   "job_key": "z5nLrqPamgi2NHpb",
# =>   "result": "Order to kill job registered"
# => }

Find a job and download a log file

The following snippets demonstrate how to search for a piece of content, identify a job, and download a log file.

Workflow

There are five steps if you need to find the content guid first. If you already know the content guid then start with step 3.

  1. Search for a piece of content by name/owner via the GET /v1/content endpoint.
  2. Note the guid for the desired content.
  3. Retrieve all jobs associated with the piece of content via the GET /v1/content/{guid}/jobs endpoint.
  4. Note the key for the specific job that is desired to be killed.
  5. Retrieve the log file for the desired job via the GET /v1/content/{guid}/jobs/{key}/download endpoint.

For steps 1-4 of this workflow, refer to the Search for a content item and job key section. For step 5 of this workflow, refer to the Download a job log file section.

Search for a content item and job key

See the Search for a content item section for instructions on how to search for a piece of content and note the guid value. Then, refer to the Search for a job key section for instructions on how to identify the specific job you desire a log file from and note the key value.

Download a job log file

Using the guid value for a content item and the key value for a specific job from the previous sections, download a log file for the desired job via the GET /v1/content/{guid}/jobs/{key}/download request.

Sample code

export CONTENT_GUID="2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
export JOB_KEY="z5nLrqPamgi2NHpb"

curl --silent --show-error -L --max-redirs 0 --fail \
    -X GET \
    -H "Authorization: Key ${CONNECT_API_KEY}" \
    "${CONNECT_SERVER}__api__/v1/content/${CONTENT_GUID}/jobs/${JOB_KEY}/download"
import requests
import os

connect_server = os.environ.get('CONNECT_SERVER')
connect_api_key = os.environ.get('CONNECT_API_KEY')

# The 'guid' value comes from an earlier /content search.
guid = "2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
# The 'key' value comes from the /content/guid/jobs search.
key = "z5nLrqPamgi2NHpb"

full_url = f"{connect_server}__api__/v1/content/{guid}/jobs/{key}/download"
headers = { 'Authorization': 'Key ' + connect_api_key }

response = requests.get(full_url, headers=headers)

print(response.text)
library(httr)

# The CONNECT_SERVER URL must have a trailing slash.
connectServer <- Sys.getenv("CONNECT_SERVER")
connectAPIKey <- Sys.getenv("CONNECT_API_KEY")

# The 'guid' value comes from an earlier /content search.
guid <- "2106c1b1-5cec-40df-a014-4ced0a4c3ccd"
# The 'key' value comes from the /content/{guid}/jobs search.
key <- "z5nLrqPamgi2NHpb"

response <- GET(
    paste0(connectServer, "__api__/v1/content/", guid, "/jobs/", key, "/download"),
    add_headers(Authorization = paste("Key", connectAPIKey))
)

print(content(response))

Sample response

2022/11/22 17:24:37.082461948 Running on host: render-r-markdown-content-68lnj-7jkf2
2022/11/22 17:24:37.253891849 Linux distribution: Ubuntu 18.04.6 LTS (bionic)
2022/11/22 17:24:37.253952700 LANG: en_US.UTF-8
2022/11/22 17:24:37.254066583 Working directory: /opt/rstudio-connect/mnt/app
2022/11/22 17:24:37.256435550 Running content using its packrat R library
2022/11/22 17:24:37.290985408 Using Packrat dir /opt/rstudio-connect/mnt/app/packrat/lib/x86_64-pc-linux-gnu/4.1.3
2022/11/22 17:24:37.305485657 R version: 4.1.3
2022/11/22 17:24:37.305741654 rmarkdown version: 2.14
2022/11/22 17:24:37.305902325 knitr version: 1.39
2022/11/22 17:24:37.306006304 reticulate version: (none)
2022/11/22 17:24:37.307765882 Using pandoc: /opt/rstudio-connect/ext/pandoc/2.16
2022/11/22 17:24:38.400072155
2022/11/22 17:24:38.400084612
2022/11/22 17:24:38.400130124 processing file: task_test_script.Rmd
  |..............                                                        |  20%
2022/11/22 17:24:38.511633182   ordinary text without R code
2022/11/22 17:24:38.511674455
  |............................                                          |  40%
2022/11/22 17:24:38.511705744 label: setup (with options)
2022/11/22 17:24:38.515700751 List of 1
2022/11/22 17:24:38.517809372  $ include: logi FALSE
2022/11/22 17:24:38.517870939
  |..........................................                            |  60%
2022/11/22 17:24:38.538655083   ordinary text without R code
2022/11/22 17:24:38.538834902
  |........................................................              |  80%
2022/11/22 17:24:38.538845912 label: cars