regionData.ts 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import { fetchMapData } from '@api/regions';
  2. import { SQLiteDatabase } from 'expo-sqlite';
  3. import { isNmDbRefreshing, refreshNmDatabase } from 'src/db';
  4. const NM_TABLES = new Set(['regions']);
  5. export const getData = async (
  6. db: SQLiteDatabase | null,
  7. regionId: number,
  8. name: string,
  9. callback: (data: any, avatars: string[]) => void
  10. ): Promise<void> => {
  11. const isNmTable = NM_TABLES.has(name);
  12. if (isNmTable && isNmDbRefreshing()) {
  13. console.warn(`[getData] nm DB is refreshing, falling back to API for "${name}"`);
  14. await fallbackToApi(regionId, callback);
  15. return;
  16. }
  17. if (!db) {
  18. if (isNmTable) {
  19. console.warn(`[getData] db is null for "${name}", falling back to API`);
  20. refreshNmDatabase();
  21. await fallbackToApi(regionId, callback);
  22. return;
  23. }
  24. throw new Error(`[getData] Database is null for table="${name}"`);
  25. }
  26. try {
  27. const regionRows = await db.getAllAsync<any>(`SELECT * FROM ${name} WHERE id = ?;`, [regionId]);
  28. const regionData = regionRows[0] ?? null;
  29. if (!regionData && isNmTable) {
  30. console.warn(
  31. `[getData] No record found for id=${regionId} in "${name}", falling back to API`
  32. );
  33. refreshNmDatabase();
  34. await fallbackToApi(regionId, callback);
  35. return;
  36. }
  37. const avatarIds: number[] = regionData?.visitors_avatars
  38. ? JSON.parse(regionData.visitors_avatars)
  39. : [];
  40. const avatars: string[] = [];
  41. for (const avatarId of avatarIds) {
  42. const avatarRows = await db.getAllAsync<any>(`SELECT * FROM avatars WHERE id = ?;`, [
  43. avatarId
  44. ]);
  45. if (avatarRows.length > 0) {
  46. avatars.push(avatarRows[0].data);
  47. }
  48. }
  49. setTimeout(() => callback(regionData, avatars), 0);
  50. } catch (error) {
  51. console.error('Error in getData:', error);
  52. if (isNmTable) {
  53. refreshNmDatabase();
  54. await fallbackToApi(regionId, callback);
  55. } else {
  56. throw error;
  57. }
  58. }
  59. };
  60. async function fallbackToApi(
  61. regionId: number,
  62. callback: (data: any, avatars: string[]) => void
  63. ): Promise<void> {
  64. try {
  65. const response = await fetchMapData(regionId);
  66. const regionData = response?.data ?? null;
  67. const avatars: string[] =
  68. regionData?.avatars?.slice(0, 3).map((a: { data: string; id: number }) => a.data) ?? [];
  69. setTimeout(() => callback(regionData, avatars), 0);
  70. } catch (apiError) {
  71. console.error('[getData] API fallback failed:', apiError);
  72. throw apiError;
  73. }
  74. }