rustler icon indicating copy to clipboard operation
rustler copied to clipboard

Add dynamic load data

Open kaaboaye opened this issue 3 years ago • 3 comments

Makes it possible to compute load_data at the runtime.

Example use case it to provide priv path to the nif.

defmodule NIF do
  use Rustler, load_data_fun: {Deployment, :nif_data}
end

defmodule Deployment do
  def nif_data do
    :code.priv_dir(:surfer_local) |> IO.iodata_to_binary()
  end
end

Also added explicit errors to indicate that user provided invalid config.

image image

kaaboaye avatar Dec 06 '21 21:12 kaaboaye

I like the idea here, but I think dynamic load_data should be a separate argument, something like load_data_fun?

As is, this will break existing load_datas that are atom pairs.

hansihe avatar Dec 07 '21 13:12 hansihe

Sure, I'll update it in the free time and ping you

kaaboaye avatar Dec 08 '21 15:12 kaaboaye

@hansihe refactored and tested on my project

kaaboaye avatar Dec 29 '21 23:12 kaaboaye

@kaaboaye do you think you could add a test for this? In rustler_test, any NIF could also load some data with that function. We could then test that this data is available.

EDIT: Also, I fixed clippy on master, so rebasing should fix clippy problems here as well I think.

evnu avatar Nov 09 '22 16:11 evnu

I've added test making use of dynamic load.

However, is this output with a couple of panics is expected?

image

kaaboaye avatar Nov 09 '22 17:11 kaaboaye

Thanks for the tests! Yes, the output is expected.

evnu avatar Nov 09 '22 19:11 evnu

The pipeline complains on windows:

 error[E0433]: failed to resolve: could not find `unix` in `os`
 --> rustler_tests\native\dynamic_load\src/lib.rs:2:47
Warning:   |
2 | use std::{ffi::OsStr, fs::read_to_string, os::unix::prelude::OsStrExt, path::PathBuf};
  |                                               ^^^^ could not find `unix` in `os`

error[E0599]: no function or associated item named `from_bytes` found for struct `OsStr` in the current scope
  --> rustler_tests\native\dynamic_load\src/lib.rs:32:28
Warning:    |
32 |     let priv_path = OsStr::from_bytes(priv_path);
   |                            ^^^^^^^^^^ function or associated item not found in `OsStr`

evnu avatar Nov 10 '22 09:11 evnu

I can fix this test for Windows but I could figure out some other case which doesn’t rely on platform specific API.

Windows fix would work as an example usage of this feature with real world use case.

but it would also mean that when adding support to other platforms this test could fail again

Should I fix it for windows or figure out something different?

kaaboaye avatar Nov 10 '22 12:11 kaaboaye

Should I fix it for windows or figure out something different?

I think fixing it for windows is sufficient. We have runners for linux, macos and windows, it suffices to only make them work for now.

evnu avatar Nov 10 '22 15:11 evnu

Looking into the issue of initialization I've realized that those modules can be also unloaded while updating. erl_nif exposes unload function for that purpose. It's mainly development issue. Hot module reloads will leak the DATASET unless upgrade and/or unload is provided.

So maybe instead of making sure that the DATASET is initialized only once we should make sure that upgrades are properly handled?

Does anyone here have any experience with how upgrades work? Does the library get new "static" memory space or is it reusing the old memory?

kaaboaye avatar Nov 15 '22 10:11 kaaboaye

Does anyone here have any experience with how upgrades work? Does the library get new "static" memory space or is it reusing the old memory?

We have a long-standing issue w.r.t. upgrades: https://github.com/rusterlium/rustler/issues/13. Currently, upgrading is not allowed.

So maybe instead of making sure that the DATASET is initialized only once we should make sure that upgrades are properly handled?

As upgrades are not supported right now, we can probably revisit that part later on. But maybe we need to figure out how to handle unload. I think this is probably not called usually, but only if an upgrade will happen?

evnu avatar Nov 15 '22 15:11 evnu

But maybe we need to figure out how to handle unload.

I think unsafe { DATASET = None } should be enough. Rust should drop Some(dataset) after that. Assuming that OTP will wait with unload until all pending function calls return.

kaaboaye avatar Nov 17 '22 10:11 kaaboaye

Ok, so only the test on windows is left here I think.

evnu avatar Nov 22 '22 10:11 evnu

Added windows support, all tests are green on windows now.

kaaboaye avatar Mar 19 '23 17:03 kaaboaye

@kaaboaye thanks for all your work! Can you try to rebase one more time on master? We had some changes to the CI, which should make the tests run more reliably. With that, I think we can then merge here.

evnu avatar Mar 28 '23 19:03 evnu

Done

kaaboaye avatar Mar 29 '23 10:03 kaaboaye

Seems that there is a merge conflict, can you resolve that?

evnu avatar Mar 29 '23 14:03 evnu

@philss resolved the merge conflict, thanks!

evnu avatar Apr 19 '23 19:04 evnu