Ensure video titles and metadata reflect database edits

Update video fetching logic to merge database edits with CDN content, fixing issues with displayed titles and ensuring data consistency across the platform.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1/DVlzRoR
This commit is contained in:
sebastjanartic 2025-09-04 06:33:23 +00:00
parent 7fecb3629f
commit 3c7aef0fa5
4 changed files with 69 additions and 44 deletions

View File

@ -40,4 +40,4 @@ args = "npm run dev"
waitForPort = 5000
[agent]
integrations = ["javascript_database==1.0.0", "javascript_google_analytics==1.0.0"]
integrations = ["javascript_google_analytics==1.0.0", "javascript_database==1.0.0"]

View File

@ -418,9 +418,10 @@ function CategoryRow({ category, onVideoClick, hideScrollButtons = false }: Cate
style={{
textShadow: '4px 4px 8px rgba(0,0,0,0.8), -2px -2px 4px rgba(0,0,0,0.6)',
WebkitTextStroke: '2px rgba(0,0,0,0.8)',
fontFeatureSettings: 'normal'
fontFeatureSettings: 'normal',
fontVariantNumeric: 'normal'
}}>
{String(index + 1)}
{(index + 1).toString()}
</div>
)}
<VideoCard

View File

@ -797,7 +797,7 @@ class BunnyStorage implements IStorage {
async getVideos(limit = 20, offset = 0, search?: string): Promise<Video[]> {
console.log(`Fetching videos from cache: limit=${limit}, offset=${offset}, search=${search}`);
const result = videoSyncService.getVideos(limit, offset, search);
const result = await videoSyncService.getVideos(limit, offset, search);
console.log(`Returning ${result.videos.length} videos from cache (age: ${result.cacheAge}ms)`);
// Apply face detection data from cache
@ -808,36 +808,18 @@ class BunnyStorage implements IStorage {
}
async getVideo(id: string): Promise<Video | undefined> {
// Try cache first for faster loading
const cachedVideo = videoSyncService.getVideos(100, 0).videos.find(v => v.id === id);
if (cachedVideo) {
// Apply cached view counts
if (this.viewsCache.has(cachedVideo.id)) {
cachedVideo.views += this.viewsCache.get(cachedVideo.id)!;
}
// Apply face detection data from cache
const faceData = this.faceDataCache.get(cachedVideo.id);
return faceData ? { ...cachedVideo, ...faceData } : cachedVideo;
// Use videoSyncService which now merges with database edits
const video = await videoSyncService.getVideo(id);
if (!video) return undefined;
// Apply cached view counts
if (this.viewsCache.has(video.id)) {
video.views += this.viewsCache.get(video.id)!;
}
// Fallback to direct API call
try {
const video = await this.bunnyService.getVideo(id);
if (!video) return undefined;
// Apply cached view counts
if (this.viewsCache.has(video.id)) {
video.views += this.viewsCache.get(video.id)!;
}
// Apply face detection data from cache
const faceData = this.faceDataCache.get(video.id);
return faceData ? { ...video, ...faceData } : video;
} catch (error) {
console.error(`Error fetching video ${id} from Bunny:`, error);
return undefined;
}
// Apply face detection data from cache
const faceData = this.faceDataCache.get(video.id);
return faceData ? { ...video, ...faceData } : video;
}
async createVideo(video: InsertVideo): Promise<Video> {
@ -860,15 +842,12 @@ class BunnyStorage implements IStorage {
console.warn(`Database update failed for video ${id}, using cache:`, dbError);
}
// If database update was successful, just update local cache - don't sync from Bunny.net
// If database update was successful, force video sync refresh
if (dbUpdateSuccessful) {
try {
const existing = this.videos.get(id);
if (existing) {
const updatedVideo = { ...existing, ...updates, updatedAt: new Date() };
this.videos.set(id, updatedVideo);
console.log(`Updated video ${id} in local cache`);
}
// Force videoSyncService to refresh this specific video
console.log(`Updated video ${id} in database, forcing cache refresh`);
videoSyncService.forceVideoRefresh(id);
} catch (cacheError) {
console.warn('Failed to update local cache after video update:', cacheError);
}

View File

@ -220,13 +220,13 @@ class VideoSyncService {
console.log('📅 Scheduled video sync every 5 minutes for optimal performance');
}
getVideos(limit: number = 20, offset: number = 0, search?: string) {
let filteredVideos = this.cache.videos;
async getVideos(limit: number = 20, offset: number = 0, search?: string) {
let filteredVideos = await this.mergeWithDatabaseEdits(this.cache.videos);
// Fast client-side search
if (search && search.length >= 2) {
const searchLower = search.toLowerCase();
filteredVideos = this.cache.videos.filter(video =>
filteredVideos = filteredVideos.filter(video =>
video.title.toLowerCase().includes(searchLower) ||
video.description?.toLowerCase().includes(searchLower)
);
@ -242,15 +242,60 @@ class VideoSyncService {
};
}
private async mergeWithDatabaseEdits(bunnyVideos: any[]) {
try {
// Fetch all edited videos from database
const dbVideos = await db.select().from(videos);
const dbVideoMap = new Map(dbVideos.map(v => [v.id, v]));
// Merge Bunny.net data with database edits
return bunnyVideos.map(bunnyVideo => {
const dbVideo = dbVideoMap.get(bunnyVideo.id);
if (dbVideo) {
// Database has edited version - use edited metadata but keep Bunny.net URLs
return {
...bunnyVideo,
title: dbVideo.title,
description: dbVideo.description,
category: dbVideo.category,
tags: dbVideo.tags || [],
customThumbnailUrl: dbVideo.customThumbnailUrl,
isPublic: dbVideo.isPublic,
updatedAt: dbVideo.updatedAt
};
}
return bunnyVideo; // No database edits - use original Bunny.net data
});
} catch (error) {
console.warn('Failed to merge database edits, using Bunny.net data only:', error);
return bunnyVideos;
}
}
async getVideo(id: string) {
// First try cache
const cachedVideo = this.cache.videos.find(v => v.id === id);
if (cachedVideo) {
return cachedVideo;
// Merge with database edits
const mergedVideos = await this.mergeWithDatabaseEdits([cachedVideo]);
return mergedVideos[0];
}
// Fallback to direct API call
return await this.bunnyService.getVideo(id);
const bunnyVideo = await this.bunnyService.getVideo(id);
if (bunnyVideo) {
const mergedVideos = await this.mergeWithDatabaseEdits([bunnyVideo]);
return mergedVideos[0];
}
return bunnyVideo;
}
forceVideoRefresh(videoId: string) {
console.log(`🔄 Forcing refresh for video ${videoId}`);
// Remove video from cache to force fresh fetch
this.cache.videos = this.cache.videos.filter(v => v.id !== videoId);
// Mark cache as needing update
this.cache.lastUpdate = 0;
}
getCacheStats() {