feat: optimize JSON sync with 1 API call + raw URLs
- Replace GitHub API calls (390+) with 1 API call + raw URL downloads - Create GitHubJsonService for efficient JSON file syncing - Reduce API rate limiting issues by 99.7% - Add automatic page reload after successful sync - Update tests to use new service - Maintain same functionality with better performance Performance improvement: - Before: 390+ GitHub API calls (1 per JSON file) - After: 1 GitHub API call + 389 raw URL downloads - Raw URLs have no rate limits, making sync much more reliable
This commit is contained in:
@@ -19,9 +19,11 @@ vi.mock('~/server/lib/git', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('~/server/services/github', () => ({
|
||||
githubService: {
|
||||
vi.mock('~/server/services/githubJsonService', () => ({
|
||||
githubJsonService: {
|
||||
syncJsonFiles: vi.fn(),
|
||||
getAllScripts: vi.fn(),
|
||||
getScriptBySlug: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
@@ -212,8 +214,8 @@ describe('scriptsRouter', () => {
|
||||
it('should return script on success', async () => {
|
||||
const mockScript = { name: 'Test Script', slug: 'test-script' }
|
||||
|
||||
const { localScriptsService } = await import('~/server/services/localScripts')
|
||||
vi.mocked(localScriptsService.getScriptBySlug).mockResolvedValue(mockScript)
|
||||
const { githubJsonService } = await import('~/server/services/githubJsonService')
|
||||
vi.mocked(githubJsonService.getScriptBySlug).mockResolvedValue(mockScript)
|
||||
|
||||
const result = await caller.getScriptBySlug({ slug: 'test-script' })
|
||||
|
||||
@@ -224,8 +226,8 @@ describe('scriptsRouter', () => {
|
||||
})
|
||||
|
||||
it('should return error when script not found', async () => {
|
||||
const { localScriptsService } = await import('~/server/services/localScripts')
|
||||
vi.mocked(localScriptsService.getScriptBySlug).mockResolvedValue(null)
|
||||
const { githubJsonService } = await import('~/server/services/githubJsonService')
|
||||
vi.mocked(githubJsonService.getScriptBySlug).mockResolvedValue(null)
|
||||
|
||||
const result = await caller.getScriptBySlug({ slug: 'nonexistent' })
|
||||
|
||||
@@ -239,35 +241,36 @@ describe('scriptsRouter', () => {
|
||||
|
||||
describe('resyncScripts', () => {
|
||||
it('should resync scripts successfully', async () => {
|
||||
const mockGitHubScripts = [
|
||||
{ name: 'Script 1', slug: 'script-1' },
|
||||
{ name: 'Script 2', slug: 'script-2' },
|
||||
]
|
||||
|
||||
const { githubService } = await import('~/server/services/github')
|
||||
const { localScriptsService } = await import('~/server/services/localScripts')
|
||||
const { githubJsonService } = await import('~/server/services/githubJsonService')
|
||||
|
||||
vi.mocked(githubService.getAllScripts).mockResolvedValue(mockGitHubScripts)
|
||||
vi.mocked(localScriptsService.saveScriptsFromGitHub).mockResolvedValue(undefined)
|
||||
vi.mocked(githubJsonService.syncJsonFiles).mockResolvedValue({
|
||||
success: true,
|
||||
message: 'Successfully synced 2 scripts from GitHub using 1 API call + raw downloads',
|
||||
count: 2
|
||||
})
|
||||
|
||||
const result = await caller.resyncScripts()
|
||||
|
||||
expect(result).toEqual({
|
||||
success: true,
|
||||
message: 'Successfully synced 2 scripts from GitHub to local directory',
|
||||
message: 'Successfully synced 2 scripts from GitHub using 1 API call + raw downloads',
|
||||
count: 2,
|
||||
})
|
||||
})
|
||||
|
||||
it('should return error on failure', async () => {
|
||||
const { githubService } = await import('~/server/services/github')
|
||||
vi.mocked(githubService.getAllScripts).mockRejectedValue(new Error('GitHub error'))
|
||||
const { githubJsonService } = await import('~/server/services/githubJsonService')
|
||||
vi.mocked(githubJsonService.syncJsonFiles).mockResolvedValue({
|
||||
success: false,
|
||||
message: 'GitHub error',
|
||||
count: 0
|
||||
})
|
||||
|
||||
const result = await caller.resyncScripts()
|
||||
|
||||
expect(result).toEqual({
|
||||
success: false,
|
||||
error: 'GitHub error',
|
||||
message: 'GitHub error',
|
||||
count: 0,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@ import { z } from "zod";
|
||||
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||
import { scriptManager } from "~/server/lib/scripts";
|
||||
import { gitManager } from "~/server/lib/git";
|
||||
import { githubService } from "~/server/services/github";
|
||||
import { githubJsonService } from "~/server/services/githubJsonService";
|
||||
import { localScriptsService } from "~/server/services/localScripts";
|
||||
import { scriptDownloaderService } from "~/server/services/scriptDownloader";
|
||||
|
||||
@@ -97,11 +97,11 @@ export const scriptsRouter = createTRPCRouter({
|
||||
}
|
||||
}),
|
||||
|
||||
// Get all scripts from local directory
|
||||
// Get all scripts from GitHub (1 API call + raw downloads)
|
||||
getAllScripts: publicProcedure
|
||||
.query(async () => {
|
||||
try {
|
||||
const scripts = await localScriptsService.getAllScripts();
|
||||
const scripts = await githubJsonService.getAllScripts();
|
||||
return { success: true, scripts };
|
||||
} catch (error) {
|
||||
return {
|
||||
@@ -112,12 +112,12 @@ export const scriptsRouter = createTRPCRouter({
|
||||
}
|
||||
}),
|
||||
|
||||
// Get script by slug from local directory
|
||||
// Get script by slug from GitHub (1 API call + raw downloads)
|
||||
getScriptBySlug: publicProcedure
|
||||
.input(z.object({ slug: z.string() }))
|
||||
.query(async ({ input }) => {
|
||||
try {
|
||||
const script = await localScriptsService.getScriptBySlug(input.slug);
|
||||
const script = await githubJsonService.getScriptBySlug(input.slug);
|
||||
if (!script) {
|
||||
return {
|
||||
success: false,
|
||||
@@ -135,20 +135,17 @@ export const scriptsRouter = createTRPCRouter({
|
||||
}
|
||||
}),
|
||||
|
||||
// Resync scripts from GitHub repo to local directory
|
||||
// Resync scripts from GitHub (1 API call + raw downloads)
|
||||
resyncScripts: publicProcedure
|
||||
.mutation(async () => {
|
||||
try {
|
||||
// First, try to get scripts from GitHub
|
||||
const githubScripts = await githubService.getAllScripts();
|
||||
|
||||
// Save scripts to local directory
|
||||
await localScriptsService.saveScriptsFromGitHub(githubScripts);
|
||||
// Sync JSON files using 1 API call + raw downloads
|
||||
const result = await githubJsonService.syncJsonFiles();
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Successfully synced ${githubScripts.length} scripts from GitHub to local directory`,
|
||||
count: githubScripts.length
|
||||
success: result.success,
|
||||
message: result.message,
|
||||
count: result.count
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error in resyncScripts:', error);
|
||||
|
||||
Reference in New Issue
Block a user