Skip to content

Commit cc60e66

Browse files
authored
Make daemons(...) return the compute profile or NULL invisibly (#389)
* Make daemons(...) return the compute profile or NULL invisibly * Add news item * Inrcrement dev version & update readme * Update vignettes * Update reference vignette
1 parent 04ac8b9 commit cc60e66

File tree

14 files changed

+156
-185
lines changed

14 files changed

+156
-185
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: mirai
33
Title: Minimalist Async Evaluation Framework for R
4-
Version: 2.4.1.9000
4+
Version: 2.4.1.9001
55
Authors@R: c(
66
person("Charlie", "Gao", , "[email protected]", role = c("aut", "cre"),
77
comment = c(ORCID = "0000-0002-0750-061X")),

NEWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# mirai (development version)
22

3+
#### Behavioural Changes
4+
5+
* `daemons()` creating new daemons returns invisibly the character compute profile created.
6+
`daemons(0)` or `daemons(NULL)` resetting daemons returns invisible NULL (thanks @eliocamp, #384).
7+
38
#### New Features
49

510
* New `with_daemons()` and `local_daemons()` helper functions for using a particular compute profile.

R/daemons.R

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@
7777
#' `tls` is encrypted with a password) For security, should be provided
7878
#' through a function that returns this value, rather than directly.
7979
#'
80-
#' @return The integer number of daemons launched locally (zero if specifying
81-
#' `url` or using a remote launcher).
80+
#' @return Invisibly, the character compute profile created, or else NULL when
81+
#' resetting daemons.
8282
#'
8383
#' @section Local Daemons:
8484
#'
@@ -261,12 +261,12 @@ daemons <- function(
261261
n <- as.integer(n)
262262

263263
n == 0L && {
264-
is.null(envir) && return(0L)
264+
is.null(envir) && return(invisible())
265265

266266
if (signal) send_signal(envir)
267267
reap(envir[["sock"]])
268268
..[[.compute]] <- NULL -> envir
269-
return(0L)
269+
return(invisible())
270270
}
271271
if (is.null(envir)) {
272272
n > 0L || stop(._[["n_zero"]])
@@ -286,7 +286,7 @@ daemons <- function(
286286
}
287287
}
288288

289-
`class<-`(envir[["n"]], c("miraiDaemons", .compute))
289+
invisible(`class<-`(.compute, "miraiDaemons"))
290290
}
291291

292292
#' @export
@@ -325,7 +325,7 @@ print.miraiDaemons <- function(x, ...) print(unclass(x))
325325
#'
326326
with.miraiDaemons <- function(data, expr, ...) {
327327
prev_profile <- .[["cp"]]
328-
`[[<-`(., "cp", class(data)[2L])
328+
`[[<-`(., "cp", data)
329329
on.exit({
330330
daemons(0L)
331331
`[[<-`(., "cp", prev_profile)

README.Rmd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ install.packages("mirai")
6060
```{r}
6161
#| label: exec
6262
library(mirai)
63-
6463
daemons(5)
6564
6665
m <- mirai({

README.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@ remote, on which to run mirai tasks.
5050

5151
``` r
5252
library(mirai)
53-
5453
daemons(5)
55-
#> [1] 5
5654

5755
m <- mirai({
5856
Sys.sleep(1)
@@ -75,7 +73,6 @@ mp[.flat]
7573
#> [1] 1 4 9 16 25 36 49 64 81
7674

7775
daemons(0)
78-
#> [1] 0
7976
```
8077

8178
### Design Concepts

dev/vignettes/_v03-serialization.Rmd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@ It can be seen that this time, the arrow table is handled seamlessly.
6262
This is the case even when the object is deeply nested inside lists or other structures.
6363

6464
Multiple serialization functions may be registered to handle different object classes.
65-
As an example, we can use Arrow in combination with [`polars`](https://pola-rs.github.io/r-polars/), a 'lightning fast' dataframe library written in Rust (requires `polars` >= 0.16.4), in the following way:
65+
As an example, we can use Arrow in combination with [`polars`](https://pola-rs.github.io/r-polars/), a 'lightning fast' dataframe library written in Rust (requires polars >= 1.0.0), in the following way:
6666
```{r}
6767
#| label: polars
6868
daemons(
6969
n = 1,
7070
serial = serial_config(
71-
c("ArrowTabular", "RPolarsDataFrame"),
72-
list(arrow::write_to_raw, function(x) polars::as_polars_df(x)$to_raw_ipc()),
73-
list(function(x) arrow::read_ipc_stream(x, as_data_frame = FALSE), polars::pl$read_ipc)
71+
c("ArrowTabular", "polars_data_frame"),
72+
list(arrow::write_to_raw, \(x) x$serialize()),
73+
list(function(x) arrow::read_ipc_stream(x, as_data_frame = FALSE), polars::pl$deserialize_df)
7474
)
7575
)
7676

man/daemons.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/tests.R

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
# minitest - a minimal testing framework v0.0.2 --------------------------------
1+
# minitest - a minimal testing framework v0.0.3 --------------------------------
22
test_library <- function(package) library(package = package, character.only = TRUE)
33
test_true <- function(x) invisible(isTRUE(x) || {print(x); stop("the above was returned instead of TRUE")})
44
test_null <- function(x) invisible(is.null(x) || {print(x); stop("the above was returned instead of NULL")})
55
test_zero <- function(x) invisible(x == 0L || {print(x); stop("the above was returned instead of 0L")})
6+
test_nzchar <- function(x) invisible(is.character(x) && nzchar(x) || {print(x); stop("the above was returned instead of a string")})
67
test_type <- function(type, x) invisible(typeof(x) == type || {stop("object of type '", typeof(x), "' was returned instead of '", type, "'")})
78
test_class <- function(class, x) invisible(inherits(x, class) || {stop("object of class '", paste(class(x), collapse = ", "), "' was returned instead of '", class, "'")})
89
test_equal <- function(a, b) invisible(a == b || {print(a); print(b); stop("the above expressions were not equal")})
@@ -17,7 +18,7 @@ connection <- !is_error_value(collect_mirai(mirai(TRUE, .timeout = 2000L)))
1718
test_type("list", status())
1819
test_zero(status()[["connections"]])
1920
test_zero(status()[["daemons"]])
20-
test_zero(daemons(0L))
21+
test_null(daemons(0L))
2122
test_error(mirai(), "missing expression, perhaps wrap in {}?")
2223
test_error(mirai(a, 1), "all `...` arguments must be named")
2324
test_error(mirai(a, .args = list(1)), "all items in `.args` must be named")
@@ -81,7 +82,7 @@ connection && {
8182
m <- mirai(mirai::on_daemon(), .timeout = 2000L)
8283
if (!is_error_value(m[])) test_true(m[])
8384
Sys.sleep(1L)
84-
test_equal(1L, d <- daemons(1L, dispatcher = FALSE, asyncdial = FALSE, seed = 1546L))
85+
test_equal("default", d <- daemons(1L, dispatcher = FALSE, asyncdial = FALSE, seed = 1546L))
8586
test_print(d)
8687
test_error(daemons(1L), "daemons already set")
8788
test_true(daemons_set())
@@ -109,9 +110,9 @@ connection && {
109110
test_print(mlc)
110111
test_error(launch_remote(1L, remote = remote_config(command = "echo", args = "invalid")), "must be an element")
111112
test_error(launch_remote(3L, remote = remote_config(command = "echo", args = list(c("test", "."), c("test", ".")))), "must equal the length")
112-
test_zero(daemons(0L))
113+
test_null(daemons(0L))
113114
Sys.sleep(1L)
114-
test_equal(1L, daemons(1L, dispatcher = FALSE, maxtasks = 10L, walltime = 10000L, idletime = 20000L, cleanup = FALSE, output = TRUE, .compute = "new"))
115+
test_equal("new", daemons(1L, dispatcher = FALSE, maxtasks = 10L, walltime = 10000L, idletime = 20000L, cleanup = FALSE, output = TRUE, .compute = "new"))
115116
test_type("character", nextget("url", .compute = "new"))
116117
test_type("integer", nextstream(.compute = "new"))
117118
test_true(require_daemons("new", call = environment()))
@@ -133,21 +134,21 @@ connection && {
133134
test_type("integer", status(.compute = "new")[["connections"]])
134135
test_error(mirai_map(1:2, "a function", .compute = "new"), "must be of type function, not character")
135136
test_error(daemons(url = local_url(), .compute = "new"), "daemons already set")
136-
test_zero(daemons(0L, .compute = "new"))
137+
test_null(daemons(0L, .compute = "new"))
137138
}
138139
# additional daemons tests
139140
connection && {
140141
Sys.sleep(1L)
141-
test_zero(daemons(url = value <- local_url(), dispatcher = FALSE))
142+
test_nzchar(daemons(url = value <- local_url(), dispatcher = FALSE))
142143
test_identical(status()$daemons, value)
143144
test_identical(nextget("url"), value)
144145
test_type("character", launch_remote(remote = remote_config(command = "echo", args = list(c("Test out:", ".", ">/dev/null")), rscript = "/usr/lib/R/bin/Rscript")))
145146
test_error(launch_remote(remote = ssh_config("ssh://127.0.0.1:5456", tunnel = TRUE)), "127.0.0.1")
146-
test_zero(daemons(0L))
147+
test_null(daemons(0L))
147148
Sys.sleep(1L)
148-
test_zero(daemons(n = 2L, url = value <- "ws://:0", dispatcher = "none", remote = remote_config(quote = TRUE)))
149+
test_nzchar(daemons(n = 2L, url = value <- "ws://:0", dispatcher = "none", remote = remote_config(quote = TRUE)))
149150
test_true(status()$daemons != value)
150-
test_zero(daemons(0L))
151+
test_null(daemons(0L))
151152
}
152153
# mirai_map tests
153154
connection && {
@@ -161,7 +162,7 @@ connection && {
161162
test_equal(length(m), 3L)
162163
test_true(all(as.logical(lapply(m, is.numeric))))
163164
Sys.sleep(1L)
164-
daemons(1, dispatcher = FALSE)
165+
test_nzchar(daemons(1, dispatcher = FALSE))
165166
mp <- mirai_map(list(x = "a"), function(...) do(...), do = function(x, y) sprintf("%s%s", x, y), .args = list("b"))
166167
test_print(mp)
167168
test_identical(collect_mirai(mp)[["x"]], "ab")
@@ -173,7 +174,7 @@ connection && {
173174
test_type("language", mirai_map(list(quote(1+2)), identity)[][[1]])
174175
test_class("Date", mirai_map(data.frame(x = as.Date("2020-01-01")), identity)[][[1]])
175176
test_true(is_mirai_error(mirai_map(1:2, function(x) daemons(1))[][[1]]))
176-
test_zero(daemons(0L))
177+
test_null(daemons(0L))
177178
}
178179
# parallel cluster tests
179180
library(parallel)
@@ -244,10 +245,10 @@ connection && {
244245
# advanced daemons and dispatcher tests
245246
connection && Sys.getenv("NOT_CRAN") == "true" && {
246247
Sys.sleep(0.5)
247-
test_zero(daemons(url = "ws://:0", correctype = 0L, token = TRUE))
248-
test_zero(daemons(0L))
248+
test_nzchar(daemons(url = "ws://:0", correctype = 0L, token = TRUE))
249+
test_null(daemons(0L))
249250
test_zero(with(daemons(url = "tcp://:0", correcttype = c(1, 0), token = TRUE), {8L - 9L + 1L}))
250-
test_zero(daemons(n = 2, "ws://:0"))
251+
test_nzchar(daemons(n = 2, "ws://:0"))
251252
test_type("integer", nextget("pid"))
252253
test_equal(length(nextget("url")), 1L)
253254
Sys.sleep(1L)
@@ -258,16 +259,16 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
258259
test_zero(status[["mirai"]][["awaiting"]])
259260
test_zero(status[["mirai"]][["executing"]])
260261
test_zero(status[["mirai"]][["completed"]])
261-
test_zero(daemons(0))
262-
test_equal(daemons(2, correcttype = NA), 2L)
262+
test_null(daemons(0))
263+
test_nzchar(daemons(2, correcttype = NA))
263264
test_equal(daemons()[["connections"]], 2L)
264265
test_type("list", res <- mirai_map(c(1,1), rnorm)[.progress])
265266
test_true(res[[1L]] != res[[2L]])
266267
test_equal(2L, daemons()[["connections"]])
267268
Sys.sleep(0.5)
268-
test_zero(daemons(0L))
269+
test_null(daemons(0L))
269270
Sys.sleep(1L)
270-
test_zero(daemons(url = "tls+tcp://127.0.0.1:0", dispatcher = TRUE))
271+
test_nzchar(daemons(url = "tls+tcp://127.0.0.1:0", dispatcher = TRUE))
271272
test_type("character", launch_remote(remote = ssh_config(c("ssh://remotehost", "ssh://remotenode"), tunnel = TRUE, command = "echo")))
272273
test_equal(launch_local(), 1L)
273274
Sys.sleep(1L)
@@ -276,20 +277,20 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
276277
m <- mirai("Seattle", .timeout = 1000)
277278
if (!is_error_value(m[])) test_equal(m[], "Seattle")
278279
test_class("errorValue", mirai(q(), .timeout = 1000)[])
279-
test_zero(daemons(0))
280+
test_null(daemons(0))
280281
Sys.sleep(0.5)
281-
test_zero(daemons(n = 1L, url = local_url(), dispatcher = TRUE))
282+
test_nzchar(daemons(n = 1L, url = local_url(), dispatcher = TRUE))
282283
task <- mirai(substitute())
283284
url <- nextget("url")
284285
test_equal(3L, daemon(url = url, maxtasks = 1L, cleanup = 0L, dispatcher = TRUE))
285-
test_zero(daemons(n = 0L))
286+
test_null(daemons(n = 0L))
286287
test_type("integer", .Random.seed)
287288
}
288289
# TLS tests
289290
connection && Sys.getenv("NOT_CRAN") == "true" && {
290291
Sys.sleep(0.5)
291292
cfg <- serial_config("custom", function(x) serialize(x, NULL), unserialize)
292-
test_zero(daemons(url = host_url(), pass = "test", serial = cfg))
293+
test_nzchar(daemons(url = host_url(), pass = "test", serial = cfg))
293294
if (.Platform$OS.type == "unix") test_type("character", launch_remote(remote = cluster_config(command = "/bin/sh", options = "#SBATCH", rscript = file.path(R.home("bin"), "Rscript"))))
294295
test_equal(launch_local(1L), 1L)
295296
Sys.sleep(1L)
@@ -299,23 +300,23 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
299300
test_zero(sum(collect_mirai(mm, ".flat")))
300301
m <- mirai(b, .timeout = 1000)
301302
if (!is_error_value(m[])) test_equal(m[], 2L)
302-
test_zero(daemons(0))
303+
test_null(daemons(0))
303304
test_tls <- function(cert) {
304305
file <- tempfile()
305306
on.exit(unlink(file))
306307
cat(cert[["server"]], file = file)
307-
daemons(url = "tls+tcp://127.0.0.1:0", tls = file, tlscert = cert[["client"]]) == 0L &&
308+
nzchar(daemons(url = "tls+tcp://127.0.0.1:0", tls = file, tlscert = cert[["client"]])) &&
308309
is.character(nextget("tls")) &&
309310
grepl("cert.pem", launch_remote(tlscert = "cert.pem"), fixed = TRUE) &&
310-
daemons(0L) == 0L
311+
is.null(daemons(0L))
311312
}
312313
test_true(test_tls(nanonext::write_cert(cn = "127.0.0.1")))
313314
}
314315
# promises tests
315316
connection && requireNamespace("promises", quietly = TRUE) && Sys.getenv("NOT_CRAN") == "true" && {
316317
run_now <- getNamespace("later")[["run_now"]]
317318
Sys.sleep(0.5)
318-
test_equal(daemons(1, notused = "wrongtype"), 1L)
319+
test_nzchar(daemons(1, notused = "wrongtype"))
319320
test_true(grepl("://", launch_remote(1L), fixed = TRUE))
320321
test_true(promises::is.promise(p1 <- promises::as.promise(mirai("completed"))))
321322
test_true(promises::is.promise(p2 <- promises::`%...>%`(mirai(Sys.sleep(0.1)), identity())))
@@ -337,12 +338,12 @@ connection && requireNamespace("promises", quietly = TRUE) && Sys.getenv("NOT_CR
337338
test_identical(names(mp[]), c("a", "b"))
338339
test_class("errorValue", mirai_map(1, function(x) stop(x), .promise = list(identity, identity))[][[1L]])
339340
run_now(1L)
340-
test_zero(daemons(NULL))
341+
test_null(daemons(NULL))
341342
}
342343
# mirai daemon limits tests
343344
connection && Sys.getenv("NOT_CRAN") == "true" && {
344345
Sys.sleep(0.5)
345-
test_equal(daemons(1, cleanup = FALSE, maxtasks = 2L, id = 125L), 1L)
346+
test_nzchar(daemons(1, cleanup = FALSE, maxtasks = 2L, id = 125L))
346347
test_true(daemons_set("default"))
347348
test_equal(mirai(1)[], mirai(1)[])
348349
m <- mirai(0L)
@@ -357,22 +358,22 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
357358
res <- status()
358359
test_zero(res$connections)
359360
test_identical(res$events, c(129L, -129L))
360-
test_zero(daemons(0))
361-
test_equal(daemons(1, dispatcher = FALSE, maxtasks = 1L), 1L)
361+
test_null(daemons(0))
362+
test_nzchar(daemons(1, dispatcher = FALSE, maxtasks = 1L))
362363
test_zero(mirai(0L)[])
363364
Sys.sleep(0.5)
364365
test_zero(status()$connections)
365366
test_equal(launch_local(1, idletime = 200L, walltime = 1000L), 1L)
366367
test_zero(mirai(0)[])
367368
Sys.sleep(1L)
368369
test_zero(status()$connections)
369-
test_zero(daemons(0))
370+
test_null(daemons(0))
370371
}
371372
# mirai cancellation tests
372373
connection && Sys.getenv("NOT_CRAN") == "true" && {
373374
Sys.sleep(0.5)
374375
Sys.unsetenv("R_DEFAULT_PACKAGES")
375-
test_equal(daemons(1, dispatcher = TRUE, cleanup = FALSE), 1L)
376+
test_nzchar(daemons(1, dispatcher = TRUE, cleanup = FALSE))
376377
m1 <- mirai({ Sys.sleep(1); res <<- "m1 done" })
377378
m2 <- mirai({ Sys.sleep(1); res <<- "m2 done" })
378379
Sys.sleep(0.1)
@@ -390,14 +391,14 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
390391
test_equal(status()$connections, 1L)
391392
test_equal(length(nextget("url")), 1L)
392393
test_class("miraiLaunchCmd", launch_remote(1))
393-
test_zero(daemons(0))
394+
test_null(daemons(0))
394395
}
395396
# additional stress testing
396397
connection && Sys.getenv("NOT_CRAN") == "true" && {
397398
Sys.sleep(0.5)
398399
q <- vector(mode = "list", length = 10000L)
399400
Sys.setenv(R_DEFAULT_PACKAGES = "stats,utils")
400-
test_equal(daemons(4), 4L)
401+
test_nzchar(daemons(4))
401402
Sys.unsetenv("R_DEFAULT_PACKAGES")
402403
test_class("mirai_map", everywhere(a <<- FALSE))
403404
test_true(all(everywhere(a <<- TRUE)[.flat]))
@@ -409,26 +410,26 @@ connection && Sys.getenv("NOT_CRAN") == "true" && {
409410
test_equal(length(unique(unlist(collect_mirai(q)))), 10000L)
410411
test_true(all(as.logical(lapply(lapply(q, attr, "status"), is.list))))
411412
test_equal(daemons()[["mirai"]][["completed"]], 20020L)
412-
test_zero(daemons(0))
413+
test_null(daemons(0))
413414
}
414415
# reproducible RNG tests
415416
connection && Sys.getenv("NOT_CRAN") == "true" && {
416-
test_equal(2L, daemons(2, seed = 1234L))
417+
test_nzchar(daemons(2, seed = 1234L))
417418
test_equal(1L, launch_local())
418419
test_type("character", launch_remote())
419420
Sys.sleep(0.5)
420421
test_true(all(everywhere(TRUE)[.flat]))
421422
m <- mirai_map(1:12, rnorm)[]
422-
test_zero(daemons(0))
423+
test_null(daemons(0))
423424
Sys.sleep(0.5)
424-
test_equal(4L, daemons(4, dispatcher = "none", seed = 1234L, .compute = "gpu"))
425+
test_equal("gpu", daemons(4, dispatcher = "none", seed = 1234L, .compute = "gpu"))
425426
with_daemons("gpu", {
426427
test_true(all(everywhere(TRUE)[.flat]))
427428
n <- mirai_map(1:12, rnorm)[]
428-
test_zero(daemons(NULL))
429+
test_null(daemons(NULL))
429430
})
430431
test_true(!daemons_set("gpu"))
431432
test_identical(m, n)
432433
}
433-
test_zero(daemons(0))
434+
test_null(daemons(0))
434435
Sys.sleep(1L)

0 commit comments

Comments
 (0)