Good way to (atomically?) persist a file when creating a record?

I'm working on a little project where one of the features is the ability to upload a file (using the :upload action which currently takes a :name and a :path as its arguments), which persists the file to disk and creates a File record in the DB. I want to do this in such a way that that I never end up with files on the disk that the DB doesn't know about, but also that no record is created if the file persistence has failed. How would I achieve this?
6 Replies
pistrie
pistrieOP5w ago
Also, I'm currently doing the following to generate a file in my tests. Is this a dumb approach or is it fine to use Ash.Generator this way?
def file_struct(_opts \\ []) do
filepath = sequence(:filepath, &Path.join(System.tmp_dir!(), "file#{&1}.md"))
filepath = filepath |> Enum.take(1) |> hd()
File.write!(filepath, filepath)

%MyApp.Files.File{
name: Path.basename(filepath),
path: filepath
}
end
def file_struct(_opts \\ []) do
filepath = sequence(:filepath, &Path.join(System.tmp_dir!(), "file#{&1}.md"))
filepath = filepath |> Enum.take(1) |> hd()
File.write!(filepath, filepath)

%MyApp.Files.File{
name: Path.basename(filepath),
path: filepath
}
end
This file struct is then used to supply the :upload action with the data it needs to perform the action (in my case, for now, it will move the file to a different location on the disk, because Phoenix LiveView uploads place the files in the /tmp dir by default)
ZachDaniel
ZachDaniel5w ago
Seems reasonable. As for doing it atomically, there isn't really any good way to do it truly atomically. Typically you'd create the file in a before_action or before_transaction hook, and then in the transaction you'd save the file into the database, and then clean up dangling files after-the-fact
pistrie
pistrieOP5w ago
alright, thanks
jart
jart5w ago
I’m doing exactly this in an after action hook though so file op failures can still blow up the transaction if they fail. https://harton.dev/james/hectic/src/branch/main/lib/assets/attachment.ex#L45
jart
jart5w ago
silly claude. why u put file in wrong place?
pistrie
pistrieOP5w ago
Interesting!

Did you find this page helpful?