--- title: "Web-app development with OpenCpu" author: "Michael Rustler" date: "`r format(Sys.time(), '%d %B, %Y')`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Web-app development with OpenCpu} %\VignetteEngine{knitr::rmarkdown} \usepackage[utf8]{inputenc} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) is_ghactions <- identical(Sys.getenv("CI"), "true") ``` ## Background For developing a web application, which is based on the R package `kwb.qmra` the [OpenCPU API](https://www.opencpu.org/api.html) can be used. It has a lot of great features which its author Jeroen Ooms describes as follows ([Source](https://www.quora.com/How-do-plumber-and-OpenCPU-compare-when-it-comes-to-deploying-ML-models)): >"OpenCPU is mature has been put to the test in production for many years now, >both in private and public organizations. The system was developed out of a need >for a reliable, scalable system for embedding R that we used at UCLA for >teaching R to students, sometimes several classes at once (think about a >classroom settings with 100+ concurrent students). >The core implementation of OpenCPU is the opencpu-server stack based on systems >native Apache2 webserver. The opencpu-server stack has been packaged as deb/rpm >packages and can be installed out of the box on all popular Linux systems. This >really provides a super stable production ready system out-of-the-box. Not only >does it easily scale up but you can configure the server (if you want to add >auth, proxies, etc) via standard Apache configuration on your server. >An incredible amount of time and energy has been invested into optimizing the >internals of opencpu-server for security, reliability and performance. In >opencpu-server, each incoming request gets processed in a temporary process fork >which serves as a sandbox that controls memory/cpu limits, access control, >timeouts, etc. All these are critical to ensure that the stability of the server >does not get compromised by users or packages (accidentally) messing with the >system or using excessive resources. I am not aware of any other R server system >that does this. > >More details about the why and how of OpenCPU are available from these papers:" > >- [Towards a Universal Interface for Scientific Computing through Separation of >Concerns](https://arxiv.org/abs/1406.4806) > >- [Enforcing Security Policies in R Using Dynamic Sandboxing on Linux](https://arxiv.org/abs/1303.4808) For the `kwb.qmra` R package a very tiny example app (source code on [GitHub](https://github.com/KWB-R/kwb.qmra/tree/master/inst/www)) was developed which uses the [OpenCPU](https://www.opencpu.org) framework. This web app performs a quantitative microbiological risk assessment (QMRA) for a [dummy configuration](https://github.com/KWB-R/kwb.qmra/tree/master/inst/extdata/configs/dummy) and can be tested here: [https://kwb-r.ocpu.io/kwb.qmra/www/](https://kwb-r.ocpu.io/kwb.qmra/www/) More advanced web-apps can be easily developed by using the [OpenCPU API](https://www.opencpu.org/api.html) but will most probably need an own backend server which hosts the OpenCPU server, because the [publically freely available OpenCPU server](https://www.opencpu.org/cloud.html) might be too limited. ```{r setup, echo = FALSE} library(kwb.qmra) data(config_dummy_json) data(config_default_json) writeLines(text = config_dummy_json, "config_dummy.json") writeLines(text = config_default_json, "config_default.json") ``` ```{r input_ghactions, echo=FALSE, results='asis', eval=is_ghactions} cat("## Run risk simulatation You need to provide the input parameters for `kwb.qmra::opencpu_simulate_risk()` required in a JSON data structure as provided in the example data [config_dummy.json](../config_dummy.json) (for details see: `kwb.qmra::config_dummy_json`), which needs to be converted into an R list data structure (see below)" ) ``` ```{r input_nonghactions, echo=FALSE, results='asis', eval=!is_ghactions} cat("## Run risk simulatation You need to provide the input parameters for `kwb.qmra::opencpu_simulate_risk()` required in a JSON data structure as provided in the example data [config_dummy.json](config_dummy.json) (for details see: `kwb.qmra::config_dummy_json`), which needs to be converted into an R list data structure (see below)" ) ``` ```{r} ### Convert "config.json" to R list config <- jsonlite::fromJSON("config_dummy.json") ### Optionally directly import a configuration from CSV files ### for details see: https://github.com/KWB-R/kwb.qmra/tree/master/inst/extdata/configs # config_dir <- system.file("extdata/configs/dummy", package = "kwb.qmra") # config <- kwb.qmra::config_read(confDir = config_dir) # Run risk simulation risk_dummy <- kwb.qmra::opencpu_simulate_risk(config) risk_dummy_json <- jsonlite::toJSON(risk_dummy, pretty = TRUE) # Save simulation results in JSON format writeLines(text = risk_dummy_json, "risk_dummy.json") ``` ```{r output_ghactions, echo=FALSE, results='asis', eval=is_ghactions} cat("The structure of the optimisation results is stored in JSON format in the R object `predictions` and also saved. For inspecting it please open the [risk_dummy.json](../risk_dummy.json) file." ) ``` ```{r output_nonghactions, echo=FALSE, results='asis', eval=!is_ghactions} cat("The structure of the optimisation results is stored in JSON format in the R object `predictions` and also saved. For inspecting it please open the [risk_dummy.json](risk_dummy.json) file." ) ``` ```{r conclusion_ghactions, echo=FALSE, results='asis', eval=is_ghactions} cat("Real calculations should be performed using the [config_default.json](../config_default.json) configuration developed by Christoph Sprenger (@chsprenger). However, due to the large size of the resulting `risk_default.json` object (~ 275MB) this default example could not be hosted at GitHub (maximum single file size <100MB). Thus this workflow was limited to the `dummy` configuration only!") ```