Packmatic.Source.Dynamic (Packmatic v2.0.0)

View Source

Represents content which may be generated on-demand, for example by another subsystem or via downloading from a signed URL.

For example, a function which dynamically generates a URL (perhaps a signed S3 URL in your own use case) would look like this:

iex(1)> url = "https://example.com"
iex(2)> init_arg = fn -> {:ok, {:url, url}} end
iex(3)> {:ok, {module, source}} = Packmatic.Source.Dynamic.init(init_arg)
iex(4)> module
Packmatic.Source.URL
iex(5)> source.__struct__
Packmatic.Source.URL

And when used within a Manifest, it would look like this:

iex(1)> url = "https://example.com"
iex(2)> init_arg = fn -> {:ok, {:url, url}} end
iex(3)> entry = [source: {:dynamic, init_arg}, path: "foo.pdf"]
iex(4)> manifest = Packmatic.Manifest.create([entry])
iex(5)> manifest.valid?
true

Even if the function (referenced by the Initialisation Argument) resolves cleanly, the result may still be rejected by the underlying Source, for example if the file does not exist. This kind of error “bubbles up” and is dealt with by the Encoder at runtime.

iex(1)> Packmatic.Source.Dynamic.init(fn -> {:ok, {:file, "example.pdf"}} end)
{:error, :enoent}

However, since resolution happens only when the built Stream starts to be consumed, such a Source Entry would be valid when placed in a Manifest ahead of time:

iex(1)> path = "example.pdf"
iex(2)> init_arg = fn -> {:ok, {:file, path}} end
iex(3)> entry = [source: {:dynamic, init_arg}, path: "foo.pdf"]
iex(4)> manifest = Packmatic.Manifest.create([entry])
iex(5)> manifest.valid?
true

Summary

Types

init_arg()

@type init_arg() :: resolve_fun()

init_result()

@type init_result() :: {:ok, Packmatic.Source.state()} | {:error, term()}

resolve_fun()

@type resolve_fun() :: (-> resolve_result() | resolve_result_error())

resolve_result()

@type resolve_result() :: {:ok, Packmatic.Source.entry()}

resolve_result_error()

@type resolve_result_error() :: {:error, term()}