Packages

phoenix_kit

1.7.81
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules publishing web controller post_fetching.ex
Raw

lib/modules/publishing/web/controller/post_fetching.ex

defmodule PhoenixKit.Modules.Publishing.Web.Controller.PostFetching do
@moduledoc """
Post fetching functionality for the publishing controller.
Handles fetching posts from cache and database, including:
- Slug mode posts (versioned)
- Timestamp mode posts
- Language fallback logic
"""
require Logger
alias PhoenixKit.Modules.Publishing
alias PhoenixKit.Modules.Publishing.ListingCache
# ============================================================================
# Main Fetch Functions
# ============================================================================
@doc """
Fetches a slug-mode post - iterates from highest version down, returns first published.
Falls back to primary language or first available if requested language isn't found.
"""
def fetch_post(group_slug, {:slug, post_slug}, language) do
Publishing.read_post(group_slug, post_slug, language)
end
def fetch_post(group_slug, {:timestamp, date, time}, language) do
identifier = "#{date}/#{time}"
Publishing.read_post(group_slug, identifier, language)
end
# ============================================================================
# Cache-Based Listing
# ============================================================================
@doc """
Fetches posts using cache when available, falls back to direct DB read.
Tries ListingCache (persistent_term) first for sub-microsecond reads.
On cache miss, regenerates from the database.
"""
def fetch_posts_with_cache(group_slug) do
fetch_posts_with_listing_cache(group_slug)
end
defp fetch_posts_with_listing_cache(group_slug) do
start_time = System.monotonic_time(:microsecond)
case ListingCache.read(group_slug) do
{:ok, posts} ->
elapsed_us = System.monotonic_time(:microsecond) - start_time
Logger.debug(
"[PublishingController] Cache HIT for #{group_slug} (#{elapsed_us}μs, #{length(posts)} posts)"
)
posts
{:error, :cache_miss} ->
Logger.warning(
"[PublishingController] Cache MISS for #{group_slug} - regenerating cache synchronously"
)
# Cache miss - regenerate cache synchronously to prevent race condition
# where subsequent requests (e.g., clicking a post) also hit cache miss.
# Uses lock to prevent thundering herd if multiple requests hit simultaneously.
case ListingCache.regenerate_if_not_in_progress(group_slug) do
:ok ->
elapsed_us = System.monotonic_time(:microsecond) - start_time
elapsed_ms = Float.round(elapsed_us / 1000, 1)
Logger.info(
"[PublishingController] Cache regenerated for #{group_slug} (#{elapsed_ms}ms)"
)
# Read from freshly populated cache
case ListingCache.read(group_slug) do
{:ok, posts} ->
posts
{:error, reason} ->
Logger.warning(
"[PublishingController] Cache read failed after regeneration for #{group_slug}: #{inspect(reason)}"
)
Publishing.list_posts(group_slug, nil)
end
:already_in_progress ->
elapsed_us = System.monotonic_time(:microsecond) - start_time
elapsed_ms = Float.round(elapsed_us / 1000, 1)
Logger.info(
"[PublishingController] Cache regeneration in progress for #{group_slug}, using direct DB read (#{elapsed_ms}ms)"
)
# Another request is regenerating, fall back to direct DB read
Publishing.list_posts(group_slug, nil)
{:error, reason} ->
Logger.error(
"[PublishingController] Cache regeneration failed for #{group_slug}: #{inspect(reason)}"
)
# Regeneration failed, fall back to direct DB read
Publishing.list_posts(group_slug, nil)
end
end
end
end