Skip to content

Commit

Permalink
Use caching for postlist (#5)
Browse files Browse the repository at this point in the history
* caching

* Update cachingUtils.php

* .
  • Loading branch information
atas authored Oct 15, 2023
1 parent 9bc6798 commit bcbced3
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 34 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ html
vendor
assets/styles/*.css
assets/styles/*.css.map
tmp/*.json
tmp/*.php
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,8 @@ Then create a pull request from `updates-from-upstream` branch to `main` branch

## Future Plans

### Caching Markdown files for performance in local env

Caching for page and post Markdowns in local environment will be added, so that the local dev env is always fast to
navigate between urls, regardless of how many markdowns are there.

### Pagination for posts

I am a fan of continuous scrolling and not numbered pages. We can implement continuous scrolling on the homepage but
I can't imagine if it can be helpful for sites with less than 100 posts. Even after 100 posts, it should not
be a big problem for the page to be rendered. I am open for suggestions though.
be a big problem for the page to be rendered. I am open for suggestions though.
2 changes: 1 addition & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

require_once 'layout/header.php';

$posts = get_all_posts();
$posts = updateAndGetCachedPostList();

echo "<div id='posts'>";
foreach ($posts as $post) {
Expand Down
4 changes: 2 additions & 2 deletions post.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

// Iterate through all posts and find the one with the same slug
// Not the most performant but once deployed they will all be static websites.
$post = current(array_filter(get_all_posts(), function ($post) {
$post = current(array_filter(updateAndGetCachedPostList(), function ($post) {
return $post->slug == $_GET['slug'];
}));

Expand All @@ -23,7 +23,7 @@
exit_with_not_found();
}

$tpl = get_markdown($post->filename);
$tpl = get_markdown('posts/' . $post->filename);

$page_meta->title = $tpl->meta->title ?? null;
$page_meta->type = "article";
Expand Down
3 changes: 3 additions & 0 deletions system/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ class Post {
public string $desc;
public string $slug;
public string $filename;

// When was the file modified last
public int $lastModified;
}

class PageMeta
Expand Down
26 changes: 1 addition & 25 deletions system/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

require_once(__DIR__ . "/../vendor/autoload.php");
require_once(__DIR__ . '/Types.php');
require_once(__DIR__ . '/cachingUtils.php');

$config = json_decode(file_get_contents(__DIR__ . "/../config.json"));

Expand Down Expand Up @@ -33,31 +34,6 @@ function get_markdown($path): ConvertedMarkdown
return convert_markdown($path);
}

/**
* Generate and return all posts as an array
* @return Post[]
* @throws CommonMarkException
*/
function get_all_posts(): array
{
$posts = [];
$files = glob('posts/*.md');
rsort($files);
foreach ($files as $key => $post_file_path) {
$tpl = get_markdown($post_file_path);

$postObj = new Post();
$postObj->title = $tpl->meta->title;
$postObj->desc = $tpl->meta->desc;
$postObj->slug = $tpl->meta->slug;
$postObj->filename = $post_file_path;

$posts[] = $postObj;
}

return $posts;
}

/**
* Show not found page
* @return void
Expand Down
88 changes: 88 additions & 0 deletions system/cachingUtils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php
function findMostRecentlyUpdatedFile($dir) {
$latestFile = "";
$latestTime = 0;

foreach (scandir($dir) as $file) {
// Avoid directories and only check files
if (is_file($dir . '/' . $file)) {
$fileTime = filemtime($dir . '/' . $file);
if ($fileTime > $latestTime) {
$latestTime = $fileTime;
$latestFile = $file;
}
}
}

return $latestTime;
}

/*
* TODO: This function needs refactoring, should be a class, and needs tests.
* @return Post[]
*/
function updateAndGetCachedPostList(): array
{
$cachePath = __DIR__ . '/../tmp/posts.json';
$postsDir = __DIR__ . '/../posts/';

/* @var Post[] $cachedPosts */
$cachedPosts = [];
if (file_exists($cachePath)) {
$cachedPostsJson = file_get_contents($cachePath);
$cachedPosts = json_decode($cachedPostsJson);
}

$cacheModified = false; // Flag to track modifications

// Iterate through each post in the directory
$postFiles = scandir($postsDir);
foreach ($postFiles as $postFile) {
if (is_file($postsDir . $postFile)) {
$lastModified = filemtime($postsDir . $postFile);

// Check if post is in cache and if its lastModified is outdated
$shouldUpdateCache = true;
foreach ($cachedPosts as &$cachedPost) {
if ($cachedPost->filename === $postFile && $cachedPost->lastModified >= $lastModified) {
$shouldUpdateCache = false;
break;
}
}

// If post is outdated or not in cache, update its data
if ($shouldUpdateCache) {
$tpl = get_markdown($postsDir . $postFile);

$postObj = new stdClass();
$postObj->title = $tpl->meta->title;
$postObj->desc = $tpl->meta->desc;
$postObj->slug = $tpl->meta->slug;
$postObj->filename = $postFile;
$postObj->lastModified = $lastModified;

// Replace or append the post in the cache array
$found = false;
foreach ($cachedPosts as &$cachedPost) {
if ($cachedPost->filename === $postFile) {
$cachedPost = $postObj;
$found = true;
break;
}
}
if (!$found) {
$cachedPosts[] = $postObj;
}

$cacheModified = true; // Mark that the cache has been modified
}
}
}

// Only save the updated cache if it was modified
if ($cacheModified) {
file_put_contents($cachePath, json_encode($cachedPosts, JSON_PRETTY_PRINT));
}

return $cachedPosts;
}
Empty file added tmp/index.html
Empty file.

0 comments on commit bcbced3

Please sign in to comment.