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:
parent
7fecb3629f
commit
3c7aef0fa5
2
.replit
2
.replit
@ -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"]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user