Skip to contents

The core package contract is a byte-oriented filesystem handle with explicit service selection.

library(Ropendal)

# Local filesystem via constructor.
root <- file.path(tempdir(), "ropendal-abstract-fs")
unlink(root, recursive = TRUE)
dir.create(root, recursive = TRUE)
fs <- opendal("fs", root = root)

# The same contract via URI. Put the local root in the query string so the
# example is portable across POSIX and Windows path syntax.
uri <- paste0("fs:///?root=", utils::URLencode(root, reserved = TRUE))
uri_fs <- opendal_uri(uri)
isTRUE(identical(fs_info(uri_fs)$scheme, fs_info(fs)$scheme))
#> [1] TRUE

Root-relative paths

All paths are normalized to the handle root before any operation, so clients can use portable relative paths.

fs_write(fs, "a/b/c.bin", as.raw(c(1, 2, 3)))
#> [1] TRUE
fs_read(fs, "a/b/c.bin")
#> [1] 01 02 03
fs_stat(fs, "a/b/c.bin")$path
#> [1] "a/b/c.bin"

Control knobs belong in handles

runtime_config(), layer_concurrent_limit(), and layer_timeout() are attached at construction time so all operations share the same behavior.

fs <- opendal(
  "fs",
  root = root,
  runtime = runtime_config(threads = 2),
  layers = list(
    layer_concurrent_limit(2),
    layer_timeout(request_timeout = 30, io_timeout = 30)
  )
)

Error values are first-class

Failed object creation returns values instead of throwing, which keeps remote control flow explicit.

fs_write(fs, "a.bin", as.raw(1))
#> [1] TRUE
second <- fs_write(fs, "a.bin", as.raw(2))
is_error_value(second)
#> [1] TRUE
if (is_error_value(second)) error_kind(second) else NULL
#> [1] "AlreadyExists"