fix: do not throw error when creating duplicate item in db

This commit is contained in:
Hongbo Wu 2024-01-22 10:45:47 +08:00
parent fb1d8331a4
commit a807a4a18e
2 changed files with 68 additions and 60 deletions

View file

@ -5,7 +5,6 @@ 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'
@ -126,35 +125,21 @@ export function followingServiceRouter() {
state: ArticleSavingRequestStatus.ContentNotFetched,
})
try {
const newItem = await createLibraryItem(itemToSave, userId)
logger.info('feed item saved in following')
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
)
logger.info('RSS label added to the item')
} catch (error) {
if (isUniqueViolation(error)) {
logger.info('feed item already saved')
return res.sendStatus(200)
}
logger.error('error saving feed item', error)
return res.sendStatus(500)
}
// save RSS label in the item
await createAndSaveLabelsInLibraryItem(
newItem.id,
userId,
[{ name: 'RSS' }],
feedUrl
)
logger.info('RSS label added to the item')
return res.sendStatus(200)
}
res.sendStatus(200)
})
return router
}

View file

@ -8,16 +8,18 @@ import { Label } from '../entity/label'
import { LibraryItem, LibraryItemState } from '../entity/library_item'
import { BulkActionType, InputMaybe, SortParams } from '../generated/graphql'
import { createPubSubClient, EntityType } from '../pubsub'
import { redisDataSource } from '../redis_data_source'
import {
authTrx,
getColumns,
isUniqueViolation,
queryBuilderToRawSql,
valuesToRawSql,
} from '../repository'
import { libraryItemRepository } from '../repository/library_item'
import { setRecentlySavedItemInRedis, wordsCount } from '../utils/helpers'
import { logger } from '../utils/logger'
import { parseSearchQuery } from '../utils/search'
import { redisDataSource } from '../redis_data_source'
enum ReadFilter {
ALL = 'all',
@ -806,48 +808,69 @@ export const createLibraryItems = async (
}
export const createLibraryItem = async (
libraryItem: DeepPartial<LibraryItem>,
libraryItem: DeepPartial<LibraryItem> & { originalUrl: string },
userId: string,
pubsub = createPubSubClient(),
skipPubSub = false
): Promise<LibraryItem> => {
const newLibraryItem = await authTrx(
async (tx) =>
tx.withRepository(libraryItemRepository).save({
...libraryItem,
wordCount:
libraryItem.wordCount ??
wordsCount(libraryItem.readableContent || ''),
}),
undefined,
userId
)
// set recently saved item in redis if redis is enabled
if (redisDataSource.redisClient) {
await setRecentlySavedItemInRedis(
redisDataSource.redisClient,
userId,
newLibraryItem.originalUrl
try {
const newLibraryItem = await authTrx(
async (tx) =>
tx.withRepository(libraryItemRepository).save({
...libraryItem,
wordCount:
libraryItem.wordCount ??
wordsCount(libraryItem.readableContent || ''),
}),
undefined,
userId
)
logger.info('item created', { url: libraryItem.originalUrl })
// set recently saved item in redis if redis is enabled
if (redisDataSource.redisClient) {
await setRecentlySavedItemInRedis(
redisDataSource.redisClient,
userId,
newLibraryItem.originalUrl
)
}
if (skipPubSub) {
return newLibraryItem
}
await pubsub.entityCreated<DeepPartial<LibraryItem>>(
EntityType.PAGE,
{
...newLibraryItem,
// don't send original content and readable content
originalContent: undefined,
readableContent: undefined,
},
userId
)
}
if (skipPubSub) {
return newLibraryItem
} catch (error) {
if (isUniqueViolation(error)) {
logger.info('item already created', { url: libraryItem.originalUrl })
const existingItem = await findLibraryItemByUrl(
libraryItem.originalUrl,
userId
)
if (!existingItem) {
throw new Error(`Item not found for url: ${libraryItem.originalUrl}`)
}
return existingItem
}
logger.error('error creating item', error)
throw error
}
await pubsub.entityCreated<DeepPartial<LibraryItem>>(
EntityType.PAGE,
{
...newLibraryItem,
// don't send original content and readable content
originalContent: undefined,
readableContent: undefined,
},
userId
)
return newLibraryItem
}
export const findLibraryItemsByPrefix = async (