fix: issue #3 slow rendering
This commit is contained in:
@@ -8,13 +8,19 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
alias BDS.Projects
|
||||
alias BDS.Rendering.FileSystem
|
||||
alias BDS.Rendering.Filters
|
||||
alias BDS.Rendering.RenderContext
|
||||
alias BDS.Repo
|
||||
alias BDS.StarterTemplates
|
||||
alias BDS.Tags.Tag
|
||||
alias BDS.Templates.Template
|
||||
|
||||
@spec resolve_post_template_slug(String.t(), [String.t()], [String.t()]) ::
|
||||
@spec resolve_post_template_slug(RenderContext.t() | String.t(), [String.t()], [String.t()]) ::
|
||||
String.t() | nil
|
||||
def resolve_post_template_slug(%RenderContext{} = ctx, tag_names, category_names) do
|
||||
Enum.find_value(tag_names, &Map.get(ctx.tag_template_slug_by_name, &1)) ||
|
||||
resolve_from_category_settings(ctx.metadata.category_settings || %{}, category_names)
|
||||
end
|
||||
|
||||
def resolve_post_template_slug(project_id, tag_names, category_names) do
|
||||
resolve_from_tags(project_id, tag_names) ||
|
||||
resolve_from_categories(project_id, category_names)
|
||||
@@ -40,8 +46,12 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
|
||||
defp resolve_from_categories(project_id, category_names) do
|
||||
{:ok, state} = Metadata.get_project_metadata(project_id)
|
||||
settings = state.category_settings || %{}
|
||||
resolve_from_category_settings(state.category_settings || %{}, category_names)
|
||||
end
|
||||
|
||||
defp resolve_from_category_settings(_settings, []), do: nil
|
||||
|
||||
defp resolve_from_category_settings(settings, category_names) do
|
||||
Enum.find_value(category_names, fn cat_name ->
|
||||
case Map.get(settings, cat_name) do
|
||||
%{"post_template_slug" => slug} when is_binary(slug) and slug != "" -> slug
|
||||
@@ -50,14 +60,22 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
end)
|
||||
end
|
||||
|
||||
@spec load_template_source(String.t(), atom(), String.t() | nil) ::
|
||||
@spec load_template_source(RenderContext.t() | String.t(), atom(), String.t() | nil) ::
|
||||
{:ok, String.t()} | {:error, term()}
|
||||
def load_template_source(project_id, kind, slug) do
|
||||
project = Projects.get_project!(project_id)
|
||||
def load_template_source(%RenderContext{} = ctx, kind, slug) do
|
||||
RenderContext.memoize(ctx, {:template_source, kind, slug}, fn ->
|
||||
do_load_template_source(ctx.project, ctx.project_id, kind, slug)
|
||||
end)
|
||||
end
|
||||
|
||||
def load_template_source(project_id, kind, slug) when is_binary(project_id) do
|
||||
do_load_template_source(Projects.get_project!(project_id), project_id, kind, slug)
|
||||
end
|
||||
|
||||
defp do_load_template_source(project, project_id, kind, slug) do
|
||||
case select_template(project_id, kind, slug) do
|
||||
%Template{} = template ->
|
||||
case published_template_body(template) do
|
||||
case published_template_body(project, template) do
|
||||
{:ok, _source} = ok ->
|
||||
ok
|
||||
|
||||
@@ -105,11 +123,10 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
limit: 1
|
||||
end
|
||||
|
||||
defp published_template_body(%Template{content: content}) when is_binary(content),
|
||||
defp published_template_body(_project, %Template{content: content}) when is_binary(content),
|
||||
do: {:ok, content}
|
||||
|
||||
defp published_template_body(%Template{} = template) do
|
||||
project = Projects.get_project!(template.project_id)
|
||||
defp published_template_body(project, %Template{} = template) do
|
||||
full_path = Path.join(Projects.project_data_dir(project), template.file_path)
|
||||
|
||||
case File.read(full_path) do
|
||||
@@ -124,11 +141,16 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
end
|
||||
end
|
||||
|
||||
@spec render_template(String.t(), String.t(), map()) ::
|
||||
@spec render_template(RenderContext.t() | String.t(), String.t(), map()) ::
|
||||
{:ok, String.t()} | {:error, String.t()}
|
||||
def render_template(project_id, source, assigns) do
|
||||
with {:ok, template_ast} <- Liquex.parse(source, BDS.Rendering.LiquidParser),
|
||||
{:ok, _rendered} = ok <- safe_liquex_render(template_ast, project_id, assigns) do
|
||||
def render_template(%RenderContext{} = ctx, source, assigns) do
|
||||
parse_result =
|
||||
RenderContext.memoize(ctx, {:template_ast, :erlang.md5(source)}, fn ->
|
||||
Liquex.parse(source, BDS.Rendering.LiquidParser)
|
||||
end)
|
||||
|
||||
with {:ok, template_ast} <- parse_result,
|
||||
{:ok, _rendered} = ok <- safe_liquex_render(template_ast, ctx.file_system, assigns) do
|
||||
ok
|
||||
else
|
||||
{:error, reason, line} when is_integer(line) -> {:error, "#{reason} at line #{line}"}
|
||||
@@ -136,14 +158,25 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
end
|
||||
end
|
||||
|
||||
defp safe_liquex_render(template_ast, project_id, assigns) do
|
||||
def render_template(project_id, source, assigns) when is_binary(project_id) do
|
||||
project = Projects.get_project!(project_id)
|
||||
file_system = FileSystem.new(StarterTemplates.template_roots(project))
|
||||
|
||||
with {:ok, template_ast} <- Liquex.parse(source, BDS.Rendering.LiquidParser),
|
||||
{:ok, _rendered} = ok <- safe_liquex_render(template_ast, file_system, assigns) do
|
||||
ok
|
||||
else
|
||||
{:error, reason, line} when is_integer(line) -> {:error, "#{reason} at line #{line}"}
|
||||
{:error, _message} = error -> error
|
||||
end
|
||||
end
|
||||
|
||||
defp safe_liquex_render(template_ast, file_system, assigns) do
|
||||
context =
|
||||
Liquex.Context.new(assigns,
|
||||
static_environment: assigns,
|
||||
filter_module: Filters,
|
||||
file_system: FileSystem.new(StarterTemplates.template_roots(project))
|
||||
file_system: file_system
|
||||
)
|
||||
|
||||
{result, _context} = Liquex.render!(template_ast, context)
|
||||
@@ -183,7 +216,10 @@ defmodule BDS.Rendering.TemplateSelection do
|
||||
defp bundled_template_slug(_kind, slug) when is_binary(slug) and slug != "", do: slug
|
||||
defp bundled_template_slug(kind, _slug), do: StarterTemplates.default_slug(kind)
|
||||
|
||||
@spec template_render_context(String.t()) :: Liquex.Context.t()
|
||||
@spec template_render_context(RenderContext.t() | String.t()) :: Liquex.Context.t()
|
||||
def template_render_context(%RenderContext{template_context: template_context}),
|
||||
do: template_context
|
||||
|
||||
def template_render_context(project_id) do
|
||||
project = Projects.get_project!(project_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user