Add trace files.
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled

This commit is contained in:
Yaojia Wang
2025-11-04 23:28:56 +01:00
parent 25d30295ec
commit 08b317e789
75 changed files with 26456 additions and 37017 deletions

View File

@@ -0,0 +1,238 @@
# Task 2: Implement Connection Management
**Task ID**: TASK-002
**Story**: [STORY-001](sprint_1_story_1.md)
**Sprint**: [Sprint 1](sprint_1.md)
**Estimated Hours**: 4h
**Assignee**: Frontend Developer 1
**Priority**: P0
**Status**: Not Started
---
## Task Description
Implement JWT authentication for SignalR connection, tenant group management, and connection lifecycle handling with automatic token refresh.
---
## Objectives
1. Integrate JWT token from auth context
2. Implement tenant group join/leave functionality
3. Handle token expiration and refresh
4. Add connection state management with React Context
5. Create useSignalR custom hook
---
## Implementation Steps
### Step 1: Create SignalR React Context (1.5h)
**File**: `src/services/signalr/SignalRContext.tsx`
```typescript
import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { signalRService } from './SignalRService';
import { ConnectionStatus } from './types';
import { useAuth } from '../../contexts/AuthContext'; // Assume exists
interface SignalRContextValue {
isConnected: boolean;
connectionStatus: ConnectionStatus;
service: typeof signalRService;
}
const SignalRContext = createContext<SignalRContextValue | undefined>(undefined);
export const SignalRProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const { accessToken, tenantId, isAuthenticated } = useAuth();
const [connectionStatus, setConnectionStatus] = useState<ConnectionStatus>(ConnectionStatus.Disconnected);
useEffect(() => {
if (!isAuthenticated || !accessToken || !tenantId) {
return;
}
// Connect to SignalR
const connectSignalR = async () => {
try {
await signalRService.connect(accessToken, tenantId);
} catch (error) {
console.error('SignalR connection failed:', error);
}
};
connectSignalR();
// Subscribe to status changes
const unsubscribe = signalRService.onStatusChange((status) => {
setConnectionStatus(status);
});
// Cleanup on unmount
return () => {
unsubscribe();
signalRService.disconnect();
};
}, [accessToken, tenantId, isAuthenticated]);
const isConnected = connectionStatus === ConnectionStatus.Connected;
return (
<SignalRContext.Provider value={{ isConnected, connectionStatus, service: signalRService }}>
{children}
</SignalRContext.Provider>
);
};
export const useSignalRContext = (): SignalRContextValue => {
const context = useContext(SignalRContext);
if (!context) {
throw new Error('useSignalRContext must be used within SignalRProvider');
}
return context;
};
```
---
### Step 2: Create Custom Hook (1h)
**File**: `src/hooks/useSignalR.ts`
```typescript
import { useEffect } from 'react';
import { useSignalRContext } from '../services/signalr/SignalRContext';
import { HubConnection } from '@microsoft/signalr';
export const useSignalR = () => {
const { isConnected, connectionStatus, service } = useSignalRContext();
const connection = service.getConnection();
return {
isConnected,
connectionStatus,
connection,
// Helper to register event handlers
on: (eventName: string, callback: (...args: any[]) => void) => {
useEffect(() => {
if (!connection) return;
connection.on(eventName, callback);
return () => {
connection.off(eventName, callback);
};
}, [connection, eventName, callback]);
}
};
};
```
---
### Step 3: Add Token Refresh Logic (1h)
Update `SignalRService.ts` to handle token expiration:
```typescript
// Add to SignalRService class
private tokenRefreshCallback: (() => Promise<string>) | null = null;
setTokenRefreshCallback(callback: () => Promise<string>): void {
this.tokenRefreshCallback = callback;
}
private async refreshTokenAndReconnect(tenantId: string): Promise<void> {
if (!this.tokenRefreshCallback) {
signalRLogger.error('No token refresh callback set');
return;
}
try {
const newToken = await this.tokenRefreshCallback();
await this.disconnect();
await this.connect(newToken, tenantId);
} catch (error) {
signalRLogger.error('Token refresh failed', error);
}
}
```
---
### Step 4: Integration with App (30 min)
Update `src/App.tsx`:
```typescript
import { SignalRProvider } from './services/signalr/SignalRContext';
function App() {
return (
<AuthProvider>
<SignalRProvider>
{/* Your app components */}
</SignalRProvider>
</AuthProvider>
);
}
```
---
## Acceptance Criteria
- [ ] SignalRContext provides connection status to all components
- [ ] useSignalR hook works in any component
- [ ] Connection automatically established when user logs in
- [ ] Connection automatically closed when user logs out
- [ ] Token refresh triggers reconnection
- [ ] Tenant group joined automatically on connect
---
## Deliverables
1. SignalRContext.tsx with provider
2. useSignalR.ts custom hook
3. Token refresh logic
4. Integration tests
5. Documentation
---
**Status**: Completed
**Created**: 2025-11-04
**Completed**: 2025-11-04
**Actual Hours**: 1.5h (estimated: 4h)
**Efficiency**: 38% (significantly faster than estimated)
---
## Completion Summary
**Status**: Completed
**Completed Date**: 2025-11-04
**Actual Hours**: 1.5h (estimated: 4h)
**Efficiency**: 38% (actual/estimated)
**Deliverables**:
- JWT authentication integrated with SignalR connection
- Tenant group management (join/leave functionality)
- Connection lifecycle handling with automatic token refresh
- React Context provider (useProjectHub hook)
- Connection state management fully integrated
**Git Commits**:
- Frontend: 01132ee (Connection management included in main commit)
**Notes**:
- Connection management was integrated directly into useProjectHub hook
- Automatic token refresh handled by React Context provider
- Tenant group joining implemented in connection initialization
- Exceeded acceptance criteria with robust state management