Creating A Service¶
This document describes how to create a TopChef service that will do some
non-trivial task. To create this service, we will be using HTTP calls from
the requests library, although the recommended approach is to use
topchef_client, or a client written for your language.
The Service¶
Let’s say that our service is just collecting a Free Induction Decay (FID) on a sample. We will need to think ahead of time what such a service would require, and eventually we settle on
- The length of time for which the pulse should be applied
- The number of data points to collect
We’ll also consider the free induction decay signal as being an array of integers, representing the intensity of the signal.
Creating the service will consist of
- Writing down a Service JSON Schema
- Checking The Schema
- Posting the service to TopChef
Before we send any HTTP code, we’ll go ahead and write down a JSON Schema describing our parameters, and our results. To do this, take a bottom-up approach to designing our schema.
Service JSON Schema¶
The length of time for which the pulse is applied is a floating-point number greater than 0. In JSON schema, we can write this down as
{
"title": "Pulse Time",
"description": "The length of time for which a pulse should be applied",
"type": "number",
"minimum": 0
}
The title and description fields are there to let us humans know
what the parameter does. Use of these fields will let us make our schemas
more self-documenting and easier to understand.
{
"title": "Data Points",
"description": "The number of data points to collect",
"type": "integer",
"minimum": 0
}
We’ll say that the object to be sent encodes each of these points in keys
named pulse_time and data_points respectively. The JSON schema that
matches such an object is given below. Note that both properties are also
required. In keeping with good practice, we will also add a $schema
key on the top level to let the world know what version of
JSON Schema we are using.
{
"title": "Free Induction Decay",
"description": "Describes a free induction decay experiment",
"$schema": "http://json-schema.org/schema#",
"type": "object",
"properties": {
"pulse_time": {
"title": "Pulse Time",
"description": "The length of time for which a pulse should be applied",
"type": "number",
"minimum": 0
},
"data_points": {
"title": "Data Points",
"description": "The number of data points to collect",
"type": "integer",
"minimum": 0
}
},
"required": [
"pulse_time",
"data_points"
]
}
We’ll also write down a result JSON Schema as
{
"title": "Free Induction Decay Results",
"description": "The results for an FID",
"$schema": "http://json-schema.org/schema#",
"type": "array",
"items": {
"title": "FID entry",
"description": "The entry into the FID result",
"type": "object",
"properties": {
"time": {
"description": "The amount of time in seconds since the start of the FID experiment when this datum was collected",
"type": "number",
"minimum": 0
},
"intensity": {
"description": "The recorded intensity",
"type": "number"
}
}
}
}
Checking The Schema¶
Let’s check that our result schema matches what we want to post. To do this,
we could use a JSON Schema validator built for the language that we
are working in, or the /validator endpoint provided by TopChef. The
following object will use TopChef’s validator to check whether an instance
matches a schema. This code is Python 2 compliant.
import requests
import json
class Validator(object):
"""
Checks an instance against a schema
"""
def __init__(self, topchef_url):
"""
:param str topchef_url: The URL for the base endpoint of TopChef
"""
self._topchef_url = topchef_url
def is_valid(instance, schema):
"""
:param dict instance: The instance to check
:param dict schema: The schema against which the instance is to
be checked
"""
data = {
'schema': schema,
'object': instance
}
response = requests.post(
'%s/validator' % self._topchef_url,
headers={'Content-Type': 'application/json'},
json=data
)
return response.status_code == 200
The code above sends a POST request to the API’s /validator
endpoint, and checks whether the status code is 200. If it is, the
schema is valid
Posting The Service¶
- Since we are satisfied with the service that we designed, let’s go ahead and
POSTit to TopChef. To do this, we can run code similar to the listing below
import requests
import json
def create_service(
topchef_url, service_name, service_description,
registration_schema, result_schema):
"""
:param str topchef_url: The URL to the topchef API
:param str service_name: The name of the service
:param str service_description: The service description
:param dict registration_schema: The schema for making new jobs
:param dict result_schema: The schema for posting results
"""
data = {
'name': service_name,
'description': service_description,
'job_registration_schema': registration_schema,
'job_result_schema': result_schema
}
response = requests.post(
'%s/services' % topchef_url,
headers={'Content-Type': 'application/json'},
json=data
)
assert response.status_code == 201
After we run this, we should see in our browsers that sending a GET
request to /services will give us an entry with our service in it. We
only have to do this once for each service that we make.