forked from pramitghosh/openEO.R.UDF
-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.R
98 lines (80 loc) · 2.74 KB
/
api.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
library(stars)
library(abind)
library(lubridate)
DEBUG = FALSE
#TODO define float maximum digits
source("data_transformation.R")
.measure_time = function(fun,message,envir=parent.frame()) {
if (!DEBUG) return(eval(fun,envir = envir))
tryCatch({
start = Sys.time()
return(eval(fun,envir=envir))
},error=function(e){
stop(e$message)
},finally = {
cat(message)
cat("\n")
print(Sys.time()-start)
})
}
#* Interprete JSON, divide code and data and assign classes
#* @filter check-data
check_data = function(req, res) {
if (DEBUG) {
cat("=== Started executing at endpoint /udf ===\n")
}
if (length(req$postBody) > 0) {
if (DEBUG) {
cat("Upload data:\n")
print(Sys.time()-as_datetime(as.numeric(req$HEADERS["date"]),tz=Sys.timezone()))
}
json_in = .measure_time(quote(jsonlite::fromJSON(req$postBody)),"Read json. Runtime:")
req$postBody = NULL
if (is.null(json_in$code$language) || !tolower(json_in$code$language)=="r") {
res$status = 400 #maybe 422
return(list(error = "Cannot interprete code source, due to missing programming language."))
}
req$code = json_in$code
req$data = json_in$data
if (length(req$data$raster_collection_tiles) > 0) {
class(req$data) = "RasterCollectionTile"
} else if (length(req$data$hypercubes) > 0) {
class(req$data) = "HyperCube"
} else {
res$status = 400
return(list(error = "Data other than RasterCollectionTile and Hypercube are not supported yet."))
}
}
plumber::forward()
}
#* @apiTitle R UDF API
#*
#* Takes a UDFRequest containing data and code and runs the code on the data
#*
#* @post /udf
run_UDF.json = function(req,res) {
# prepare the executable code
fun = function() {}
formals(fun) = alist(data=) #TODO also metadata from run_udf (processes api)
body(fun) = parse(text=req$code$source)
# transform data into stars
stars_in = .measure_time(quote(as(req$data,"stars")),"Translated list into stars. Runtime:")
# run the UDF
stars_out = .measure_time(quote(fun(data=stars_in)),"Executed script. Runtime:")
# transform stars into JSON
json_out = .measure_time(quote(as(stars_out,"HyperCube")),"Translated from stars to list. Runtime:")
json=.measure_time(quote(jsonlite::toJSON(json_out,auto_unbox = TRUE)),"Prepared JSON from list. Runtime:")
res$setHeader(name = "CONTENT-TYPE",value = "application/json")
res$setHeader(name = "date", value = Sys.time())
res$body = json
return(res)
}
#* Gets the library configuration of this udf service
#* @get /libs
#* @serializer unboxedJSON
#* @preempt check-data
get_installed_libraries = function() {
libs = as.data.frame(installed.packages()[,c("Package","Version")])
rownames(libs) = NULL
return(libs)
}