fix: Ozonetel token — 10min cache, invalidate on 401, refresh on login

- Reduced token cache from 55min to 10min (Ozonetel expires in ~15min)
- All API methods invalidate cached token on 401 response
- Force-refresh token on CC agent login
- Removed unused withTokenRetry wrapper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 15:22:19 +05:30
parent 2e4f97ff1a
commit fd08a5d5db
2 changed files with 22 additions and 2 deletions

View File

@@ -139,6 +139,11 @@ export class AuthController {
// Lock session in Redis with IP // Lock session in Redis with IP
await this.sessionService.lockSession(agentConfig.ozonetelAgentId, memberId, clientIp); await this.sessionService.lockSession(agentConfig.ozonetelAgentId, memberId, clientIp);
// Force-refresh Ozonetel API token on login
this.ozonetelAgent.refreshToken().catch(err => {
this.logger.warn(`Ozonetel token refresh on login failed: ${err.message}`);
});
// Login to Ozonetel with agent-specific credentials // Login to Ozonetel with agent-specific credentials
const ozAgentPassword = process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$'; const ozAgentPassword = process.env.OZONETEL_AGENT_PASSWORD ?? 'Test123$';
this.ozonetelAgent.loginAgent({ this.ozonetelAgent.loginAgent({

View File

@@ -22,6 +22,10 @@ export class OzonetelAgentService {
return this.cachedToken; return this.cachedToken;
} }
return this.refreshToken();
}
async refreshToken(): Promise<string> {
const url = `https://${this.apiDomain}/ca_apis/CAToken/generateToken`; const url = `https://${this.apiDomain}/ca_apis/CAToken/generateToken`;
this.logger.log('Generating CloudAgent API token'); this.logger.log('Generating CloudAgent API token');
@@ -32,7 +36,7 @@ export class OzonetelAgentService {
const data = response.data; const data = response.data;
if (data.token) { if (data.token) {
this.cachedToken = data.token; this.cachedToken = data.token;
this.tokenExpiry = Date.now() + 55 * 60 * 1000; this.tokenExpiry = Date.now() + 10 * 60 * 1000; // 10 min cache (Ozonetel expires in ~15 min)
this.logger.log('CloudAgent token generated successfully'); this.logger.log('CloudAgent token generated successfully');
return data.token; return data.token;
} }
@@ -40,6 +44,12 @@ export class OzonetelAgentService {
throw new Error(data.message ?? 'Token generation failed'); throw new Error(data.message ?? 'Token generation failed');
} }
private invalidateToken(): void {
this.cachedToken = null;
this.tokenExpiry = 0;
}
async loginAgent(params: { async loginAgent(params: {
agentId: string; agentId: string;
password: string; password: string;
@@ -83,6 +93,7 @@ export class OzonetelAgentService {
this.logger.log(`Agent login response: ${JSON.stringify(data)}`); this.logger.log(`Agent login response: ${JSON.stringify(data)}`);
return data; return data;
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
this.logger.error(`Agent login failed: ${error.message}`); this.logger.error(`Agent login failed: ${error.message}`);
throw error; throw error;
} }
@@ -111,10 +122,10 @@ export class OzonetelAgentService {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
}); });
this.logger.log(`Manual dial response: ${JSON.stringify(response.data)}`); this.logger.log(`Manual dial response: ${JSON.stringify(response.data)}`);
return response.data; return response.data;
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
const responseData = error?.response?.data ? JSON.stringify(error.response.data) : ''; const responseData = error?.response?.data ? JSON.stringify(error.response.data) : '';
this.logger.error(`Manual dial failed: ${error.message} ${responseData}`); this.logger.error(`Manual dial failed: ${error.message} ${responseData}`);
throw error; throw error;
@@ -304,6 +315,7 @@ export class OzonetelAgentService {
} }
return []; return [];
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
this.logger.error(`Abandon calls failed: ${error.message}`); this.logger.error(`Abandon calls failed: ${error.message}`);
return []; return [];
} }
@@ -393,6 +405,7 @@ export class OzonetelAgentService {
} }
return null; return null;
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
this.logger.error(`Agent summary failed: ${error.message}`); this.logger.error(`Agent summary failed: ${error.message}`);
return null; return null;
} }
@@ -422,6 +435,7 @@ export class OzonetelAgentService {
} }
return '00:00:00'; return '00:00:00';
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
this.logger.error(`AHT failed: ${error.message}`); this.logger.error(`AHT failed: ${error.message}`);
return '00:00:00'; return '00:00:00';
} }
@@ -459,6 +473,7 @@ export class OzonetelAgentService {
this.logger.log(`Agent logout response: ${JSON.stringify(response.data)}`); this.logger.log(`Agent logout response: ${JSON.stringify(response.data)}`);
return response.data; return response.data;
} catch (error: any) { } catch (error: any) {
if (error?.response?.status === 401) this.invalidateToken();
this.logger.error(`Agent logout failed: ${error.message}`); this.logger.error(`Agent logout failed: ${error.message}`);
throw error; throw error;
} }