Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template Plugin #53

Open
5 tasks
preaction opened this issue Jan 27, 2019 · 2 comments
Open
5 tasks

Template Plugin #53

preaction opened this issue Jan 27, 2019 · 2 comments

Comments

@preaction
Copy link
Owner

preaction commented Jan 27, 2019

It would be nice if the editor could edit the application's templates. To do this, we need to:

  1. Create a Yancy::Plugin::Template that adds a new collection (templates) to the existing Yancy backend
    • Database schema for this table should be provided for all supported backends via a named migration
    • The table should have two fields: A name (which is the full path of the template including format [e.g. html] and template handler [e.g. ep]) and a template, which is the code of the template.
  2. When the application starts, load the templates so they are available to the application
    • Register a template handler for Yancy and make it the default handler.
      • This has the benefit of allowing some routes to bypass the Yancy templates by explicitly using the ep handler
    • The Yancy template handler should render the template from a cache (use the renderer cache)
      • We will need to copy parts of the EPRenderer to enable helpers and access to the controller
      • If the template doesn't exist in the cache, look for the template in the database. If it doesn't exist in the database, defer to the EPRenderer
      • We need to expire the cache regularly through a timer: Only the one worker that responds to the editor's API request to change the template will get the backend event to fire.
    • If the above does not work well, create a subclass of Mojolicious::Renderer and install that as the app's renderer (keeping the existing app renderer as a fallback). Then Yancy has total control over rendering and can delegate to Mojolicious::Renderer as desired.
  3. Add backend events (Backend events #52) to update the internal template cache when a template is created, updated, or deleted
@mohawk2
Copy link
Contributor

mohawk2 commented Jan 27, 2019

I'd suggest a handler attribute for the plugin, which takes the name as a parameter, and defaults to a sub calling the backend getting the templates collection, but could be overridden.

I'd also suggest that loading all the templates at startup won't scale. There may need to be some caching, but that can be in a later version. This is separate from the renderer cache, which is of course essential.

I'm not sure about the last point - perhaps just an expiring cache, with a default of 10 minutes' life, instead? (I like the general "backend events" concept, of course)

@preaction
Copy link
Owner Author

preaction commented Jan 27, 2019

These are what the Mojolicious renderers do: All templates are cached upon first load from the filesystem or the data section and stored forever. The Mojolicious::Renderer cache does not expire. Reloading the app is the only way to reload the templates.

For the Yancy plugin, expiring the cache could happen on set/create/delete and then wait for the cache to be repopulated by a request (but why not just update the cache during the edit request and save the other users from having to wait?).

You're right that we will also need to expire the cache regularly through a timer: Only the one worker that responds to the editor's API request to change the template will get the backend event to fire.

The Mojolicious::Renderer's warmup sub does a scan for all the paths and data sections to find the templates. Since it won't find Yancy's, we can't override existing templates (which is a desirable feature). Reading the existing templates from the database is necessary so we can tell the renderer that the Yancy template plugin should handle those (indeed, we have to put our handler first in the list of possible handlers for that template name). There doesn't seem to be a public API for this, so we might need to say that overriding existing templates can't be done (which diminishes the usefulness of this plugin). [Edit: The other possibility if we are having to do very bad things to make this work is to create a subclass of Mojolicious::Renderer and then we have total control over rendering and can delegate to Mojolicious::Renderer as desired.]

I don't anticipate users having thousands of templates via this. If they do, they are modeling their data very wrongly. A basic markdown-based page content area can share space with this to have both static (markdown) and dynamic (template) content. We don't need to optimize for pathological cases.

If someone wants to change how templates are loaded (if not from the Yancy backend), they can write their own renderer like Yancy is. If some compelling arguments can be made for editing the Mojo::Template objects after they're created, we can add some events there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants