diff --git a/.github/workflows/R-CMD-check.yaml b/.github/workflows/R-CMD-check.yaml index eb1a694..8d60ca8 100644 --- a/.github/workflows/R-CMD-check.yaml +++ b/.github/workflows/R-CMD-check.yaml @@ -29,7 +29,7 @@ jobs: R_KEEP_PKG_SOURCE: yes steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-pandoc@v2 diff --git a/.github/workflows/pkgdown.yaml b/.github/workflows/pkgdown.yaml index 0321e5e..2c0d1fc 100644 --- a/.github/workflows/pkgdown.yaml +++ b/.github/workflows/pkgdown.yaml @@ -22,7 +22,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-pandoc@v2 @@ -41,7 +41,7 @@ jobs: - name: Deploy to GitHub pages 🚀 if: github.event_name != 'pull_request' - uses: JamesIves/github-pages-deploy-action@v4.4.1 + uses: JamesIves/github-pages-deploy-action@v4 with: clean: false branch: gh-pages diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml index cd3c582..4c84972 100644 --- a/.github/workflows/test-coverage.yaml +++ b/.github/workflows/test-coverage.yaml @@ -15,7 +15,7 @@ jobs: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: r-lib/actions/setup-r@v2 with: diff --git a/DESCRIPTION b/DESCRIPTION index c84378f..f186210 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,8 +26,8 @@ Encoding: UTF-8 Depends: R (>= 3.5) Imports: - nanonext (>= 0.10.1), - promises (>= 1.1.0) + nanonext (>= 0.13.3), + promises (>= 1.3.0) Suggests: - mirai (>= 0.10.0) + mirai (>= 0.12.1) RoxygenNote: 7.3.1 diff --git a/NAMESPACE b/NAMESPACE index 9d67898..02ccf71 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,8 +2,11 @@ S3method(as.promise,mirai) S3method(as.promise,recvAio) +S3method(is.promising,recvAio) export(polling) importFrom(nanonext,is_error_value) importFrom(nanonext,unresolved) importFrom(promises,as.promise) +importFrom(promises,is.promising) importFrom(promises,promise) +importFrom(promises,then) diff --git a/NEWS.md b/NEWS.md index 0f7b2c9..3663b74 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # mirai.promises 0.4.1.9000 (development) +* Updates promises method for improved integration with Shiny (thanks @jcheng5). +* Adds is.promising() method for 'recvAio'. +* Requires promises >= 1.3.0 and nanonext >= 0.13.3. + # mirai.promises 0.4.1 * Performance enhancements. diff --git a/R/core.R b/R/core.R index 7bb066c..9c6ab9f 100644 --- a/R/core.R +++ b/R/core.R @@ -42,20 +42,11 @@ #' (\href{https://orcid.org/0000-0002-0750-061X}{ORCID}) #' #' @importFrom nanonext is_error_value unresolved -#' @importFrom promises as.promise promise +#' @importFrom promises as.promise is.promising promise then #' "_PACKAGE" -# nocov start -# tested implicitly - -.onLoad <- function(libname, pkgname) { - - as.promise.recvAio <<- as.promise.mirai <<- as.promise.mirai() - -} - -# nocov end +. <- list2env(list(later = .getNamespace("later")[["later"]], pollfreq = 0.1)) #' Make 'Mirai' 'Promise' #' @@ -85,27 +76,51 @@ #' @export #' as.promise.mirai <- function(x) { - later <- .getNamespace("later")[["later"]] - pollfreq <- 0.1 - function(x) - promise( + force(x) + then( + promise = promise( function(resolve, reject) { query <- function() if (unresolved(x)) - later(query, delay = pollfreq) else - if (is_error_value(value <- .subset2(x, "value"))) - reject(value) else - resolve(value) + .[["later"]](query, delay = .[["pollfreq"]]) else + resolve(.subset2(x, "value")) query() } - ) + ), + onFulfilled = function(value) + if (is_error_value(value) && !mirai::is_mirai_interrupt(value)) + stop(value) else + value + ) } #' @rdname as.promise.mirai #' @method as.promise recvAio #' @export #' -as.promise.recvAio <- as.promise.mirai +as.promise.recvAio <- function(x) { + force(x) + then( + promise = promise( + function(resolve, reject) { + query <- function() + if (unresolved(x)) + .[["later"]](query, delay = .[["pollfreq"]]) else + resolve(.subset2(x, "value")) + query() + } + ), + onFulfilled = function(value) + if (is_error_value(value)) + stop(value) else + value + ) +} + +#' @method is.promising recvAio +#' @export +#' +is.promising.recvAio <- function(x) TRUE #' Set Polling Frequency #' @@ -128,7 +143,7 @@ as.promise.recvAio <- as.promise.mirai polling <- function(freq = 100L) { is.numeric(freq) || stop("'freq' must be a numeric value") - `[[<-`(environment(as.promise.mirai), "pollfreq", freq / 1000L) + `[[<-`(., "pollfreq", freq / 1000L) invisible() } diff --git a/README.Rmd b/README.Rmd index f4c064d..b98c607 100644 --- a/README.Rmd +++ b/README.Rmd @@ -17,7 +17,7 @@ knitr::opts_chunk$set( [![CRAN status](https://www.r-pkg.org/badges/version/mirai.promises?color=112d4e)](https://CRAN.R-project.org/package=mirai.promises) -[![mirai.promises status badge](https://shikokuchuo.r-universe.dev/badges/mirai.promises?color=24a60e)](https://shikokuchuo.r-universe.dev/mirai.promises) +[![mirai.promises status badge](https://shikokuchuo.r-universe.dev/badges/mirai.promises?color=ddcacc)](https://shikokuchuo.r-universe.dev/mirai.promises) [![R-CMD-check](https://github.com/shikokuchuo/mirai.promises/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/shikokuchuo/mirai.promises/actions/workflows/R-CMD-check.yaml) [![Codecov](https://codecov.io/gh/shikokuchuo/mirai.promises/branch/main/graph/badge.svg)](https://app.codecov.io/gh/shikokuchuo/mirai.promises) [![DOI](https://zenodo.org/badge/647242817.svg)](https://zenodo.org/badge/latestdoi/647242817) @@ -37,7 +37,7 @@ Install the latest release from CRAN: install.packages("mirai.promises") ``` -or the development version from rOpenSci R-universe: +Or the development version from R-universe: ```{r runiv, eval=FALSE} install.packages("mirai.promises", repos = "https://shikokuchuo.r-universe.dev") @@ -97,6 +97,8 @@ shinyApp(ui = ui, server = server) ### Thanks +[Joe Cheng](https://github.com/jcheng5) for optimising the promises method to work seamlessly within Shiny. + [Daniel Falbel](https://github.com/dfalbel/) for the original version of the above example and agreeing to its use here, as well as the specific use case that motivated this package. ### Links diff --git a/README.md b/README.md index 1e94d69..a873c34 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ [![CRAN status](https://www.r-pkg.org/badges/version/mirai.promises?color=112d4e)](https://CRAN.R-project.org/package=mirai.promises) [![mirai.promises status -badge](https://shikokuchuo.r-universe.dev/badges/mirai.promises?color=24a60e)](https://shikokuchuo.r-universe.dev/mirai.promises) +badge](https://shikokuchuo.r-universe.dev/badges/mirai.promises?color=ddcacc)](https://shikokuchuo.r-universe.dev/mirai.promises) [![R-CMD-check](https://github.com/shikokuchuo/mirai.promises/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/shikokuchuo/mirai.promises/actions/workflows/R-CMD-check.yaml) [![Codecov](https://codecov.io/gh/shikokuchuo/mirai.promises/branch/main/graph/badge.svg)](https://app.codecov.io/gh/shikokuchuo/mirai.promises) [![DOI](https://zenodo.org/badge/647242817.svg)](https://zenodo.org/badge/latestdoi/647242817) @@ -34,7 +34,7 @@ Install the latest release from CRAN: install.packages("mirai.promises") ``` -or the development version from rOpenSci R-universe: +Or the development version from R-universe: ``` r install.packages("mirai.promises", repos = "https://shikokuchuo.r-universe.dev") @@ -99,6 +99,9 @@ shinyApp(ui = ui, server = server) ### Thanks +[Joe Cheng](https://github.com/jcheng5) for optimising the promises +method to work seamlessly within Shiny. + [Daniel Falbel](https://github.com/dfalbel/) for the original version of the above example and agreeing to its use here, as well as the specific use case that motivated this package. diff --git a/tests/tests.R b/tests/tests.R index 102fd9d..7022b6a 100644 --- a/tests/tests.R +++ b/tests/tests.R @@ -1,19 +1,21 @@ -library(mirai.promises) library(nanonext) +requireNamespace("mirai", quietly = TRUE) library(promises) +library(mirai.promises) nanotest <- function(x) invisible(x || stop("is not TRUE when expected to be TRUE")) s <- socket() r <- recv_aio(s) nanotest(is.promise(as.promise(r))) +nanotest(is.promising(r)) close(s) if (requireNamespace("mirai", quietly = TRUE)) { nanotest(is.promise(p1 <- as.promise(mirai::mirai("completed")))) nanotest(is.promise(p2 <- mirai::mirai("completed") %...>% identity())) - nanotest(environment(mirai.promises:::as.promise.mirai)[["pollfreq"]] == 0.1) - nanotest(is.null(polling(freq = 1000))) - nanotest(environment(mirai.promises:::as.promise.mirai)[["pollfreq"]] == 1L) - nanotest(is.null(polling())) - nanotest(environment(mirai.promises:::as.promise.mirai)[["pollfreq"]] == 0.1) + Sys.sleep(3L) } -Sys.sleep(3L) +nanotest(mirai.promises:::.[["pollfreq"]] == 0.1) +nanotest(is.null(polling(freq = 1000))) +nanotest(mirai.promises:::.[["pollfreq"]] == 1L) +nanotest(is.null(polling())) +nanotest(mirai.promises:::.[["pollfreq"]] == 0.1)