0

I am developing a Shiny application where I need to score a series of articles asynchronously by calling an external API using my own package. I aim to run multiple promises in parallel to enhance performance and wish to update a progress bar after each promise completes.

Here's the code in the server side of the app, inside a withProgress() block:

    # Set up reactive values
    articles <- reactiveVal()
    articles(get_articles())
    scored_articles <- reactiveVal()

    # Set up parallel environment
    old_plan <- future::plan()
    future::plan(future::multisession)
    on.exit(future::plan(old_plan), add = TRUE)
    
    # Progress bar parameters init
    incProgress(.5)
    batch_size <- 20
    tot_items <- articles() |> nrow()
    
    # Score articles
    promises <- articles() |>
      group_by(grp = ceiling(row_number()/batch_size)) |> # Split dataset into chunks
      group_split() |>
      furrr::future_map(\(df) {
        message("Promise launched")
        promises::future_promise({
          score <- get_llm_score(df)
          incProgress(.5 / (tot_items/batch_size))
          score
        })
      })

    # Solve the promises
    promises::promise_all(.list = promises) |>
      promises::then(function(result) {
        # post-processing the result
        result |> bind_rows() |>
        scored_articles()
      }) |>
      promises::catch(function(error) {
        message(error)
        showNotification("An error occurred", type = "error")
      })

Something doesn't work in this implementation. This is what happens:

  • The bar gets stuck at 50% (the value that it should have before starting the promise).
  • The "Promise launched" messages are triggered much later, presumably AFTER the call to get_llm_score() has been completed, instead of before.
  • The progress bar then disappears. My hypothesis is that it gets updated all at once after all the promises have been fulfilled.
  • Then nothing happens. The app should row bind the loop output and put it into scored_articles() which should trigger the rendering of the table.

What am I doing wrong? is this the correct way to run a repeated process in parallel? how should I implement it in order to have a starting message before my function is run and a progress update once it's done?

Any insights or recommendations would be greatly appreciated.

Bakaburg
  • 3,165
  • 4
  • 32
  • 64

0 Answers0