Comparing changes
Open a pull request
- 1 commit
- 2 files changed
- 0 comments
- 1 contributor
- +1 −1 README.md
- +51 −25 app.R
| @@ -2,7 +2,7 @@ | |||
|
|
|
||
| This is a Shiny example application, meant to demonstrate how to convert synchronous (traditional) Shiny apps to asynchronous ones. | This is a Shiny example application, meant to demonstrate how to convert synchronous (traditional) Shiny apps to asynchronous ones. | ||
|
|
|
||
| This is the (naive) **asynchronous** version. The synchronous version is [here](https://github.com/jcheng5/cranwhales) ([diff](https://github.com/jcheng5/cranwhales/compare/sync...async?diff=split)). The optimized asynchronous version is [here](https://github.com/rstudio/cranwhales/tree/async2) ([diff](https://github.com/jcheng5/cranwhales/compare/async...async2?diff=split)). | This is the optimized **asynchronous** version. The synchronous version is [here](https://github.com/jcheng5/cranwhales) ([diff](https://github.com/jcheng5/cranwhales/compare/sync...async?diff=split)). The (naive) asynchronous version is [here](https://github.com/rstudio/cranwhales/tree/async) ([diff](https://github.com/jcheng5/cranwhales/compare/async...async2?diff=split)). | ||
|
|
|
||
| To learn more about asynchronous programming in R and Shiny, see https://rstudio.github.io/promises/. | To learn more about asynchronous programming in R and Shiny, see https://rstudio.github.io/promises/. | ||
|
|
|
||
| @@ -7,6 +7,7 @@ library(DT) | |||
| library(glue) | library(glue) | ||
| library(lubridate) | library(lubridate) | ||
| library(gdata) # for gdata::humanReadable | library(gdata) # for gdata::humanReadable | ||
| library(magrittr) # for extract2 | |||
|
|
|
||
| library(promises) | library(promises) | ||
| library(future) | library(future) | ||
| @@ -81,8 +82,36 @@ server <- function(input, output, session) { | |||
| } | } | ||
| }) %...>% | }) %...>% | ||
| { p$set(message = "Parsing data...") } %...>% | { p$set(message = "Parsing data...") } %...>% | ||
| { future(read_csv(path, col_types = "Dti---c-ci", progress = FALSE) %>% | { future({ | ||
| filter(!is.na(package))) } %>% | df <- read_csv(path, col_types = "Dti---c-ci", progress = FALSE) %>% | ||
| filter(!is.na(package)) | |||
| whale_ip <- df %>% | |||
| count(ip_id) %>% | |||
| arrange(desc(n)) %>% | |||
| head(25) %>% | |||
| pull(ip_id) | |||
|
|
|||
| whale_data <- df %>% filter(ip_id %in% whale_ip) | |||
|
|
|||
| all_data <- df %>% | |||
| mutate( | |||
| time = hms::trunc_hms(time, 60*60), | |||
| whale_class = match(ip_id, whale_ip) | |||
| ) %>% | |||
| count(time, whale_class) | |||
|
|
|||
| list( | |||
| whale_data = whale_data, | |||
| all_data = all_data, | |||
| stats = list( | |||
| total_size = sum(as.numeric(df$size)), | |||
| total_count = nrow(df), | |||
| total_uniques = length(unique(df$package)), | |||
| total_downloaders = length(unique(df$ip_id)) | |||
| ) | |||
| ) | |||
|
|
|||
| }) } %>% | |||
| finally(~p$close()) | finally(~p$close()) | ||
| }) | }) | ||
|
|
|
||
| @@ -99,6 +128,7 @@ server <- function(input, output, session) { | |||
| need(input$count <= 25, "Too many downloaders; 25 or fewer please") | need(input$count <= 25, "Too many downloaders; 25 or fewer please") | ||
| ) | ) | ||
| data() %...>% | data() %...>% | ||
| extract2("whale_data") %...>% | |||
| count(ip_id, country) %...>% | count(ip_id, country) %...>% | ||
| arrange(desc(n)) %...>% | arrange(desc(n)) %...>% | ||
| head(input$count) %...>% | head(input$count) %...>% | ||
| @@ -112,7 +142,7 @@ server <- function(input, output, session) { | |||
| whale_downloads <- reactive({ | whale_downloads <- reactive({ | ||
| promise_all(data = data(), whales = whales()) %...>% | promise_all(data = data(), whales = whales()) %...>% | ||
| with({ | with({ | ||
| data %>% | data$whale_data %>% | ||
| inner_join(whales, "ip_id") %>% | inner_join(whales, "ip_id") %>% | ||
| select(-n) | select(-n) | ||
| }) | }) | ||
| @@ -125,57 +155,53 @@ server <- function(input, output, session) { | |||
|
|
|
||
| output$total_size <- renderValueBox({ | output$total_size <- renderValueBox({ | ||
| data() %...>% | data() %...>% | ||
| pull(size) %...>% | extract2("stats") %...>% | ||
| as.numeric() %...>% # Cast from integer to numeric to avoid overflow warning | extract2("total_size") %...>% | ||
| sum() %...>% | |||
| humanReadable() %...>% | humanReadable() %...>% | ||
| valueBox("bandwidth consumed") | valueBox("bandwidth consumed") | ||
| }) | }) | ||
|
|
|
||
| output$total_count <- renderValueBox({ | output$total_count <- renderValueBox({ | ||
| data() %...>% | data() %...>% | ||
| nrow() %...>% | extract2("stats") %...>% | ||
| extract2("total_count") %...>% | |||
| format(big.mark = ",") %...>% | format(big.mark = ",") %...>% | ||
| valueBox("files downloaded") | valueBox("files downloaded") | ||
| }) | }) | ||
|
|
|
||
| output$total_uniques <- renderValueBox({ | output$total_uniques <- renderValueBox({ | ||
| data() %...>% | data() %...>% | ||
| pull(package) %...>% | extract2("stats") %...>% | ||
| unique() %...>% | extract2("total_uniques") %...>% | ||
| length() %...>% | |||
| format(big.mark = ",") %...>% | format(big.mark = ",") %...>% | ||
| valueBox("unique packages") | valueBox("unique packages") | ||
| }) | }) | ||
|
|
|
||
| output$total_downloaders <- renderValueBox({ | output$total_downloaders <- renderValueBox({ | ||
| data() %...>% | data() %...>% | ||
| pull(ip_id) %...>% | extract2("stats") %...>% | ||
| unique() %...>% | extract2("total_downloaders") %...>% | ||
| length() %...>% | |||
| format(big.mark = ",") %...>% | format(big.mark = ",") %...>% | ||
| valueBox("unique downloaders") | valueBox("unique downloaders") | ||
| }) | }) | ||
|
|
|
||
| output$all_hour <- renderPlot({ | output$all_hour <- renderPlot({ | ||
| promise_all(data = data(), whales = whales()) %...>% | data() %...>% | ||
| with({ | extract2("all_data") %...>% | ||
| whale_ip <- whales$ip_id | mutate( | ||
|
|
is_whale = !is.na(whale_class) & whale_class <= input$count | ||
| data %>% | ) %...>% | ||
| mutate( | group_by(time, is_whale) %...>% | ||
| time = hms::trunc_hms(time, 60*60), | summarise(n = sum(n)) %...>% | ||
| is_whale = ip_id %in% whale_ip | ungroup() %...>% { | ||
| ) %>% | ggplot(., aes(time, n, fill = is_whale)) + | ||
| count(time, is_whale) %>% | |||
| ggplot(aes(time, n, fill = is_whale)) + | |||
| geom_bar(stat = "identity") + | geom_bar(stat = "identity") + | ||
| scale_fill_manual(values = c("#666666", "#88FF99"), | scale_fill_manual(values = c("#666666", "#88FF99"), | ||
| labels = c("no", "yes")) + | labels = c("no", "yes")) + | ||
| ylab("Downloads") + | ylab("Downloads") + | ||
| xlab("Hour") + | xlab("Hour") + | ||
| scale_y_continuous(labels = scales::comma) | scale_y_continuous(labels = scales::comma) | ||
| }) | } | ||
| }) | }) | ||
|
|
|
||
| #### "Biggest whales" tab ------------------------------------- | #### "Biggest whales" tab ------------------------------------- | ||