Skip to content

Commit

Permalink
feat(server): Add sync errors to connection count (#3025)
Browse files Browse the repository at this point in the history
## Describe your changes

Adds sync errors to response from connection count so we can show it in
the UI

## Issue ticket number and link


https://linear.app/nango/issue/NAN-2168/surface-integrationsconnections-errors-in-nango-ui

## Checklist before requesting a review (skip if just adding/editing
APIs & templates)
- [ ] I added tests, otherwise the reason is: 
- [ ] I added observability, otherwise the reason is:
- [ ] I added analytics, otherwise the reason is:
  • Loading branch information
nalanj authored Nov 20, 2024
1 parent 06a04ad commit 66a1802
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const getConnectionsCount = asyncWrapper<GetConnectionsCount>(async (req,

const count = await connectionService.count({ environmentId: environment.id });
if (count.isErr()) {
res.status(200).send({ data: { total: 0, withAuthError: 0 } });
res.status(200).send({ data: { total: 0, withAuthError: 0, withSyncError: 0, withError: 0 } });
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createConfigSeed, createConfigSeeds } from '../seeders/config.seeder.js
import { createConnectionSeeds, createConnectionSeed } from '../seeders/connection.seeder.js';
import { createEnvironmentSeed } from '../seeders/environment.seeder.js';
import { errorNotificationService } from './notification/error.service.js';
import { createSyncSeeds } from '../seeders/sync.seeder.js';

describe('Connection service integration tests', () => {
beforeAll(async () => {
Expand Down Expand Up @@ -209,4 +210,47 @@ describe('Connection service integration tests', () => {
expect(connectionIds).toEqual([notionOK.connection_id]);
});
});

describe('count', () => {
it('return total and error counts', async () => {
const env = await createEnvironmentSeed();

const config = await createConfigSeed(env, 'notion', 'notion');

await createConnectionSeed(env, 'notion');

const notionAuthError = await createConnectionSeed(env, 'notion');
await errorNotificationService.auth.create({
type: 'auth',
action: 'connection_test',
connection_id: notionAuthError.id!,
log_id: Math.random().toString(36).substring(7),
active: true
});

const notionSyncError = await createConnectionSeed(env, 'notion');
const sync = await createSyncSeeds({
connectionId: notionSyncError.id!,
environment_id: env.id,
nango_config_id: config.id!,
sync_name: 'test'
});
await errorNotificationService.sync.create({
type: 'sync',
action: 'sync_test',
connection_id: notionSyncError.id!,
log_id: Math.random().toString(36).substring(7),
active: true,
sync_id: sync.sync.id
});

const countResult = await connectionService.count({ environmentId: env.id });
const count = countResult.unwrap();

expect(count.total).toBe(3);
expect(count.withAuthError).toBe(1);
expect(count.withSyncError).toBe(1);
expect(count.withError).toBe(2);
});
});
});
21 changes: 16 additions & 5 deletions packages/shared/lib/services/connection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,15 +742,21 @@ class ConnectionService {
return result.map((connection) => encryptionManager.decryptConnection(connection) as Connection);
}

public async count({ environmentId }: { environmentId: number }): Promise<Result<{ total: number; withAuthError: number }>> {
public async count({
environmentId
}: {
environmentId: number;
}): Promise<Result<{ total: number; withAuthError: number; withSyncError: number; withError: number }>> {
const query = db.knex
.from(`_nango_connections`)
.select<{ total_connection: string; with_auth_error: string }>(
.select<{ total_connection: string; with_auth_error: string; with_sync_error: string; with_error: string }>(
db.knex.raw('COUNT(_nango_connections.*) as total_connection'),
db.knex.raw('COUNT(_nango_connections.*) FILTER (WHERE _nango_active_logs.type IS NOT NULL) as with_auth_error')
db.knex.raw("COUNT(_nango_connections.*) FILTER (WHERE _nango_active_logs.type = 'auth') as with_auth_error"),
db.knex.raw("COUNT(_nango_connections.*) FILTER (WHERE _nango_active_logs.type = 'sync') as with_sync_error"),
db.knex.raw('COUNT(_nango_connections.*) FILTER (WHERE _nango_active_logs.type IS NOT NULL) as with_error')
)
.leftJoin('_nango_active_logs', (join) => {
join.on('_nango_active_logs.connection_id', '_nango_connections.id').andOnVal('active', true).andOnVal('type', 'auth');
join.on('_nango_active_logs.connection_id', '_nango_connections.id').andOnVal('active', true);
})
.where({
'_nango_connections.environment_id': environmentId,
Expand All @@ -762,7 +768,12 @@ class ConnectionService {
return Err('failed_to_count');
}

return Ok({ total: Number(res.total_connection), withAuthError: Number(res.with_auth_error) });
return Ok({
total: Number(res.total_connection),
withAuthError: Number(res.with_auth_error),
withSyncError: Number(res.with_sync_error),
withError: Number(res.with_error)
});
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/types/lib/connection/api/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export type GetConnectionsCount = Endpoint<{
};
Path: '/api/v1/connections/count';
Success: {
data: { total: number; withAuthError: number };
data: { total: number; withAuthError: number; withSyncError: number; withError: number };
};
}>;

Expand Down

0 comments on commit 66a1802

Please sign in to comment.