Tilebox languages and SDKs
Tilebox supports multiple languages and SDKs for running workflows.
All Tilebox SDKs and workflows are designed to be interoperable, which means it’s possible to have a workflow where individual tasks are executed in different languages.
Check out Languages & SDKs to learn more about currently available programming SDKs.
Why multi-language workflows?
You might need to use multiple languages in a single workflow for many reasons, such as:
- You want to use a language that is better suited for a specific task (for example Python for data processing, Go for a backend API)
- You want to use a library that is only available in a specific language (for example xarray in Python)
- You started prototyping in Python, but need to start migrating the compute-intensive parts of your workflow to a different language for performance reasons
Multi-language workflow example
This guide will tackle the first use case: you have a tasking server in Go and want to offload some of the processing to Python.
Defining tasks in Python and Go
class ScheduleImageCapture(Task):
# The input parameters must match the ones defined in the Go task
location: tuple[float, float] # lat_lon
resolution_m: int
spectral_bands: list[float] # spectral bands in nm
def execute(self, context: ExecutionContext) -> None:
# Here you can implement your task logic, submit subtasks, etc.
print(f"Image captured for {self.location} with {self.resolution_m}m resolution and bands {self.spectral_bands}")
@staticmethod
def identifier() -> tuple[str, str]:
# The identifier must match the one defined in the Go task
return "tilebox.com/schedule_image_capture", "v1.0"
type ScheduleImageCapture struct {
// json tags must match the Python task definition
Location [2]float64 `json:"location"` // lat_lon
ResolutionM int `json:"resolution_m"`
SpectralBands []float64 `json:"spectral_bands"` // spectral bands in nm
}
// No need to define the Execute method since we're only submitting the task
// Identifier must match with the task identifier in the Python runner
func (t *ScheduleImageCapture) Identifier() workflows.TaskIdentifier {
return workflows.NewTaskIdentifier("tilebox.com/schedule_image_capture", "v1.0")
}
A couple important points to note:
Creating a Go server that submits jobs
Write a simple HTTP tasking server in Go with a /submit
endpoint that accepts requests to submit a ScheduleImageCapture
job.
Both Go and Python code are using test-cluster-tZD9Ca2qsqt4V
as the cluster slug. You should replace it with your own cluster slug, which you can create in the Tilebox Console.
func main() {
log.Println("Server starting on http://localhost:8080")
client := workflows.NewClient()
http.HandleFunc("/submit", submitHandler(client))
log.Fatal(http.ListenAndServe(":8080", nil))
}
// Submit a job based on some query parameters
func submitHandler(client *workflows.Client) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
latArg := r.URL.Query().Get("lat")
lonArg := r.URL.Query().Get("lon")
resolutionArg := r.URL.Query().Get("resolution")
bandsArg := r.URL.Query().Get("bands[]")
latFloat, err := strconv.ParseFloat(latArg, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
lonFloat, err := strconv.ParseFloat(lonArg, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
resolutionM, err := strconv.Atoi(resolutionArg)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
var spectralBands []float64
for _, bandArg := range strings.Split(bandsArg, ",") {
band, err := strconv.ParseFloat(bandArg, 64)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
spectralBands = append(spectralBands, band)
}
job, err := client.Jobs.Submit(r.Context(), "Schedule Image capture",
[]workflows.Task{
&ScheduleImageCapture{
Location: [2]float64{latFloat, lonFloat},
ResolutionM: resolutionM,
SpectralBands: spectralBands,
},
},
)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_, _ = io.WriteString(w, fmt.Sprintf("Job submitted: %s\n", job.ID))
}
}
In the same way that you can submit jobs across languages you can also submit subtasks across languages.
Creating a Python runner
Write a Python script that starts a task runner and registers the ScheduleImageCapture
task.
from tilebox.workflows import Client
def main():
client = Client()
runner = client.runner(tasks=[ScheduleImageCapture])
runner.run_forever()
if __name__ == "__main__":
main()
Testing it
Start the Go server.
In another terminal, start the Python runner.
Submit a job to the Go server.
curl http://localhost:8080/submit?lat=40.75&lon=-73.98&resolution=30&bands[]=489.0,560.6,666.5
Check the Python runner output, it should print the following line:
Image captured for [40.75, -73.98] with 30m resolution and bands [489, 560.6, 666.5]
Next Steps
As a learning exercise, you can try to change the News API Workflow to replace the FetchNews
task with a Go task and keep all the other tasks in Python.
You’ll learn how to submit a subtask in another language than what the current task is executed in.