4) support • Improved caching • Improved accessibility ◦ UI elements include suitable ARIA attributes ◦ Language attribute (lang argument added to all *Page() functions) ◦ Alternate text for renderPlot() • Shiny Developer Mode
render functions can cache their values, using the bindCache() function. In other words, the application will do the computation with a given set of inputs once, and then after that, if those inputs are seen again, it can simply retrieve the value saved in the cache, instead of having to compute it again. Mastering Shiny Chapter
(test, prod) • Release is when that code (feature) is made available to users Application-based release patterns vs. Environment-based release patterns DevOps Learning: Decouple deployment from release
GUIDs by content name and owner New patterns for release and deployment management - Bundle promotion now `/v1` - Blue-green option through `/vanity` swapping APP 1 APP 2 Vanity URL Path
the current state of the app in its URL - Add a bookmarkButton() to the UI - Turn ui into a function - Add enableBookmarking = "url" to the shinyApp() call Instead of providing an explicit button, another option is to automatically update the URL in the browser. Server Bookmarking Storing richer state Issues with URL bookmarking - URL is going to get very long if you have a large number of inputs, and it’s not going to be able to capture an uploaded file. use enableBookmarking = "server", which saves the state to an .rds file on the server. This always generates a short, opaque, URL but requires additional storage on the server. (Not supported on shinyapps.io today)
open source tool for “Collaborative Annotation” - Annotate the web, with anyone, anywhere - Free and open to use If you want to write custom JavaScript code to customize and extend your Shiny app, you’ll eventually need to figure out how to get Shiny to serve up your JavaScript.
Rambling, Cluttered - Parts that work well - Parts that work not-so well Local Development EDA, Prototyping, Iteration The “Lightning-Talk” of Data Products - Targeted - Elegant - Streamlined - Optimized Production Development
Use shinyloadtest to see if app is fast enough 2. If not, use profvis to see what’s making it slow 3. Optimize a. Move work out of shiny (very often) b. Make code faster (very often) c. Use caching (sometimes) d. Use async (occasionally) 4. Repeat!
built to scale content. Publishers and administrators have access to runtime settings to help tune and scale their applications and APIs. The scheduling parameters tell RStudio Connect to act somewhere in between Scenario A and Scenario B, to maximize the trade-off between app responsiveness and memory consumption/load time. Max processes - Determines the maximum number of processes that will be created. Max connections per process - The maximum number of connections per process.
for different types of content. 1. Shiny applications - records information about each visit and the length of that visit. 2. Static and rendered content - records information about each visit. github.com/sol-eng/connect-usage Code examples showing how to access the instrumentation data are in the User Activity recipes within the RStudio Connect API Cookbook.
code of your app. Instead either put them in environment variables, or if you have many use the config package. Make sure that they are never included in your source code control by adding the appropriate files to .gitignore. Document how a new developer can get the appropriate credentials. Example: Shiny Data Level Security Levels: • Server • Application • Data
for valid input are performed by JavaScript in the browser, not by R. This means it’s possible for a knowledgeable attacker to send values that you don’t expect.
a big warning sign for any Shiny app - Never source() an uploaded .R file - Never rmarkdown::render() an uploaded .Rmd Common functions that parse(), eval(), or both, in a way that you’re not aware of: - Model formulas - Glue labels - Variable transformation
you want to allow a user to supply a glue string to generate a label, instead use glue::glue_safe() which only looks up variable names and doesn’t evaluate code: The glue package provides a powerful way to create strings from data
Application? - Who is the audience? - What is your service level agreement definition? (SLA) - What does your analytic architecture look like today? - What are your goals for evolving this architecture? - How will monitoring be handled? - Who is responsible for maintenance? Make work visible, Define shared goals, Build a checklist, Iterate Empathetic Communication is Challenging What does ‘Production’ mean? Keep it up: unplanned outages are rare or nonexistent Keep it safe: data, functionality, and code are all kept safe from unauthorized users Keep it correct: works as intended, provides the right answers Keep it snappy: fast response times, ability to predict needed capacity for expected traffic
Access/Security Performance Tuning Shared Goal: Shorten the distance between development and production Shared Goal: The improvement of daily work Shared Goal: Reduce the risk of deploying a breaking change Testing! Automated Testing! Getting a Sandbox!