diff --git a/src/contexts/NeoInstituteContext.tsx b/src/contexts/NeoInstituteContext.tsx index e0fc0a7..4c36deb 100644 --- a/src/contexts/NeoInstituteContext.tsx +++ b/src/contexts/NeoInstituteContext.tsx @@ -5,6 +5,8 @@ import { SchoolNeoDBService } from '../services/graph/schoolNeoDBService'; import { CCSchoolNodeProps } from '../utils/tldraw/cc-base/cc-graph/cc-graph-types'; import { logger } from '../debugConfig'; +const NEO_INSTITUTE_TIMEOUT_MS = 8000; + export interface NeoInstituteContextType { schoolNode: CCSchoolNodeProps | null; isLoading: boolean; @@ -22,7 +24,7 @@ const NeoInstituteContext = createContext({ export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ children }) => { const { user } = useAuth(); const { profile, isInitialized: isUserInitialized } = useUser(); - + const [schoolNode, setSchoolNode] = useState(null); const [isLoading, setIsLoading] = useState(true); const [isInitialized, setIsInitialized] = useState(false); @@ -35,7 +37,7 @@ export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ childr hasUser: !!user, isInitialized }); - + // Wait for user profile to be ready if (!isUserInitialized) { logger.debug('neo-institute-context', '⏳ Waiting for user initialization...'); @@ -58,7 +60,17 @@ export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ childr userEmail: user?.email }); - const node = await SchoolNeoDBService.getSchoolNode(profile.school_db_name); + // Race the Neo4j call against a timeout so a slow/unavailable Neo4j + // never blocks the workspace from loading for more than 8 seconds. + const timeoutPromise = new Promise((_, reject) => + setTimeout(() => reject(new Error(`Neo4j timed out after ${NEO_INSTITUTE_TIMEOUT_MS}ms`)), NEO_INSTITUTE_TIMEOUT_MS) + ); + + const node = await Promise.race([ + SchoolNeoDBService.getSchoolNode(profile.school_db_name), + timeoutPromise + ]); + if (node) { setSchoolNode(node); logger.debug('neo-institute-context', '✅ School node loaded', { @@ -71,7 +83,7 @@ export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ childr } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Failed to load school node'; - logger.error('neo-institute-context', '❌ Failed to load school node', { + logger.warn('neo-institute-context', '⚠️ School node unavailable — workspace will load without institute data', { error: errorMessage, schoolDbName: profile.school_db_name }); @@ -79,7 +91,7 @@ export const NeoInstituteProvider: React.FC<{ children: ReactNode }> = ({ childr } finally { setIsLoading(false); setIsInitialized(true); - logger.debug('neo-institute-context', '✅ Institute context initialization complete'); + logger.debug('neo-institute-context', '✅ Institute context initialization complete'); } };