diff --git a/packages/api/src/repository/index.ts b/packages/api/src/repository/index.ts index 973e09434..943dc0dd8 100644 --- a/packages/api/src/repository/index.ts +++ b/packages/api/src/repository/index.ts @@ -1,5 +1,12 @@ import * as httpContext from 'express-http-context2' -import { EntityManager, EntityTarget, QueryBuilder, Repository } from 'typeorm' +import { DatabaseError } from 'pg' +import { + EntityManager, + EntityTarget, + QueryBuilder, + QueryFailedError, + Repository, +} from 'typeorm' import { appDataSource } from '../data_source' import { Claims } from '../resolvers/types' import { SetClaimsRole } from '../utils/dictionary' @@ -106,3 +113,15 @@ export const valuesToRawSql = ( return sql } + +const isQueryFailedError = ( + err: unknown +): err is QueryFailedError & DatabaseError => err instanceof QueryFailedError + +export const isUniqueViolation = (err: unknown): boolean => { + if (isQueryFailedError(err)) { + return err.code === '23505' + } + + return false +} diff --git a/packages/api/src/routers/svc/following.ts b/packages/api/src/routers/svc/following.ts index 261dbf4ee..2251d94e9 100644 --- a/packages/api/src/routers/svc/following.ts +++ b/packages/api/src/routers/svc/following.ts @@ -5,6 +5,7 @@ import { PageType, PreparedDocumentInput, } from '../../generated/graphql' +import { isUniqueViolation } from '../../repository' import { createAndSaveLabelsInLibraryItem } from '../../services/labels' import { createLibraryItem } from '../../services/library_item' import { parsedContentToLibraryItem } from '../../services/save_page' @@ -125,18 +126,29 @@ export function followingServiceRouter() { state: ArticleSavingRequestStatus.ContentNotFetched, }) - const newItem = await createLibraryItem(itemToSave, userId) - logger.info('feed item saved in following') + try { + const newItem = await createLibraryItem(itemToSave, userId) + logger.info('feed item saved in following') - // save RSS label in the item - await createAndSaveLabelsInLibraryItem( - newItem.id, - userId, - [{ name: 'RSS' }], - feedUrl - ) + // save RSS label in the item + await createAndSaveLabelsInLibraryItem( + newItem.id, + userId, + [{ name: 'RSS' }], + feedUrl + ) - logger.info('RSS label added to the item') + logger.info('RSS label added to the item') + } catch (error) { + logger.error('error saving feed item', error) + + if (isUniqueViolation(error)) { + logger.info('feed item already saved') + return res.sendStatus(200) + } + + return res.sendStatus(500) + } return res.sendStatus(200) }