Merge pull request #3714 from omnivore-app/fix/db-connections

This commit is contained in:
Jackson Harper
2024-03-23 10:35:18 +08:00
committed by GitHub
7 changed files with 41 additions and 100 deletions

View File

@ -4,7 +4,6 @@
/* eslint-disable @typescript-eslint/require-await */
import axios from 'axios'
import { XMLParser } from 'fast-xml-parser'
import { QueryRunner } from 'typeorm'
import { v4 } from 'uuid'
import { appDataSource } from '../../data_source'
import {
@ -14,7 +13,6 @@ import {
DiscoverFeed,
MutationAddDiscoverFeedArgs,
} from '../../generated/graphql'
import { EntityType } from '../../pubsub'
import { authorized } from '../../utils/gql-utils'
import { RSS_PARSER_CONFIG } from '../../utils/parser'
@ -63,25 +61,23 @@ const extractRssData = (
})
const handleExistingSubscription = async (
queryRunner: QueryRunner,
feed: DiscoverFeed,
userId: string
): Promise<AddDiscoverFeedSuccess | AddDiscoverFeedError> => {
// Add to existing, otherwise conflict.
const existingSubscription = await queryRunner.query(
const existingSubscription = await appDataSource.query(
'SELECT * FROM omnivore.discover_feed_subscription WHERE user_id = $1 and feed_id = $2',
[userId, feed.id]
)
if (existingSubscription.rows > 1) {
await queryRunner.release()
return {
__typename: 'AddDiscoverFeedError',
errorCodes: [AddDiscoverFeedErrorCode.Conflict],
}
}
const addSubscription = await queryRunner.query(
await appDataSource.query(
'INSERT INTO omnivore.discover_feed_subscription(feed_id, user_id) VALUES($1, $2)',
[feed.id, userId]
)
@ -93,7 +89,6 @@ const handleExistingSubscription = async (
}
const addNewSubscription = async (
queryRunner: QueryRunner,
url: string,
userId: string
): Promise<AddDiscoverFeedSuccess | AddDiscoverFeedError> => {
@ -135,7 +130,7 @@ const addNewSubscription = async (
}
const discoverFeedId = v4()
await queryRunner.query(
await appDataSource.query(
'INSERT INTO omnivore.discover_feed(id, title, link, image, type, description) VALUES($1, $2, $3, $4, $5, $6)',
[
discoverFeedId,
@ -147,12 +142,11 @@ const addNewSubscription = async (
]
)
await queryRunner.query(
await appDataSource.query(
'INSERT INTO omnivore.discover_feed_subscription(feed_id, user_id) VALUES($2, $1)',
[userId, discoverFeedId]
)
await queryRunner.release()
return {
__typename: 'AddDiscoverFeedSuccess',
feed: { ...feed, id: discoverFeedId } as DiscoverFeed,
@ -165,24 +159,16 @@ export const addDiscoverFeedResolver = authorized<
MutationAddDiscoverFeedArgs
>(async (_, { input: { url } }, { uid, log, pubsub }) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
const existingFeed = (await queryRunner.query(
const existingFeed = (await appDataSource.query(
'SELECT id from omnivore.discover_feed where link = $1',
[url]
)) as DiscoverFeedRows
if (existingFeed.rows.length > 0) {
return await handleExistingSubscription(
queryRunner,
existingFeed.rows[0],
uid
)
return await handleExistingSubscription(existingFeed.rows[0], uid)
}
const result = await addNewSubscription(queryRunner, url, uid)
const result = await addNewSubscription(url, uid)
// TODO: Add pubsub for new feed
// if (result.__typename == 'AddDiscoverFeedSuccess') {
// await pubsub.entityCreated(

View File

@ -1,4 +1,5 @@
import { authorized } from '../../../utils/gql-utils'
import { v4 } from 'uuid'
import { appDataSource } from '../../../data_source'
import {
InputMaybe,
MutationSaveDiscoverArticleArgs,
@ -7,11 +8,9 @@ import {
SaveDiscoverArticleSuccess,
SaveSuccess,
} from '../../../generated/graphql'
import { appDataSource } from '../../../data_source'
import { QueryRunner } from 'typeorm'
import { userRepository } from '../../../repository/user'
import { saveUrl } from '../../../services/save_url'
import { v4 } from 'uuid'
import { authorized } from '../../../utils/gql-utils'
export const saveDiscoverArticleResolver = authorized<
SaveDiscoverArticleSuccess,
@ -24,10 +23,6 @@ export const saveDiscoverArticleResolver = authorized<
{ uid, log }
) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
const user = await userRepository.findById(uid)
if (!user) {
return {
@ -36,7 +31,7 @@ export const saveDiscoverArticleResolver = authorized<
}
}
const { rows: discoverArticles } = (await queryRunner.query(
const { rows: discoverArticles } = (await appDataSource.query(
`SELECT url FROM omnivore.discover_feed_articles WHERE id=$1`,
[discoverArticleId]
)) as {
@ -73,13 +68,11 @@ export const saveDiscoverArticleResolver = authorized<
const saveSuccess = savedArticle as SaveSuccess
await queryRunner.query(
await appDataSource.query(
`insert into omnivore.discover_feed_save_link (discover_article_id, user_id, article_save_id, article_save_url) VALUES ($1, $2, $3, $4) ON CONFLICT ON CONSTRAINT user_discover_feed_link DO UPDATE SET (article_save_id, article_save_url, deleted) = ($3, $4, false);`,
[discoverArticleId, uid, saveSuccess.clientRequestId, saveSuccess.url]
)
await queryRunner.release()
return {
__typename: 'SaveDiscoverArticleSuccess',
url: saveSuccess.url,

View File

@ -1,15 +1,14 @@
import { authorized } from '../../../utils/gql-utils'
import { appDataSource } from '../../../data_source'
import { LibraryItemState } from '../../../entity/library_item'
import {
DeleteDiscoverArticleError,
DeleteDiscoverArticleErrorCode,
DeleteDiscoverArticleSuccess,
MutationDeleteDiscoverArticleArgs,
} from '../../../generated/graphql'
import { appDataSource } from '../../../data_source'
import { QueryRunner } from 'typeorm'
import { userRepository } from '../../../repository/user'
import { updateLibraryItem } from '../../../services/library_item'
import { LibraryItemState } from '../../../entity/library_item'
import { authorized } from '../../../utils/gql-utils'
export const deleteDiscoverArticleResolver = authorized<
DeleteDiscoverArticleSuccess,
@ -17,10 +16,6 @@ export const deleteDiscoverArticleResolver = authorized<
MutationDeleteDiscoverArticleArgs
>(async (_, { input: { discoverArticleId } }, { uid, log, pubsub }) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
const user = await userRepository.findById(uid)
if (!user) {
return {
@ -29,7 +24,7 @@ export const deleteDiscoverArticleResolver = authorized<
}
}
const { rows: discoverArticles } = (await queryRunner.query(
const { rows: discoverArticles } = (await appDataSource.query(
`SELECT article_save_id FROM omnivore.discover_feed_save_link WHERE discover_article_id=$1 and user_id=$2`,
[discoverArticleId, uid]
)) as {
@ -43,7 +38,7 @@ export const deleteDiscoverArticleResolver = authorized<
}
}
await queryRunner.query(
await appDataSource.query(
`UPDATE omnivore.discover_feed_save_link set deleted = true WHERE discover_article_id=$1 and user_id=$2`,
[discoverArticleId, uid]
)
@ -58,8 +53,6 @@ export const deleteDiscoverArticleResolver = authorized<
pubsub
)
await queryRunner.release()
return {
__typename: 'DeleteDiscoverArticleSuccess',
id: discoverArticleId,

View File

@ -1,12 +1,11 @@
import { authorized } from '../../../utils/gql-utils'
import {
GetDiscoverFeedArticleSuccess,
GetDiscoverFeedArticleError,
QueryGetDiscoverFeedArticlesArgs,
GetDiscoverFeedArticleErrorCode,
} from '../../../generated/graphql'
import { appDataSource } from '../../../data_source'
import { QueryRunner } from 'typeorm'
import {
GetDiscoverFeedArticleError,
GetDiscoverFeedArticleErrorCode,
GetDiscoverFeedArticleSuccess,
QueryGetDiscoverFeedArticlesArgs,
} from '../../../generated/graphql'
import { authorized } from '../../../utils/gql-utils'
const COMMUNITY_FEED_ID = '8217d320-aa5a-11ee-bbfe-a7cde356f524'
@ -28,7 +27,6 @@ type DiscoverFeedArticleDBRows = {
}
const getPopularTopics = (
queryRunner: QueryRunner,
uid: string,
after: string,
amt: number,
@ -38,10 +36,10 @@ const getPopularTopics = (
if (feedId) {
params.push(feedId)
}
return queryRunner.query(
return appDataSource.query(
`
SELECT id, title, feed_id as feed, slug, description, url, author, image, published_at, COALESCE(sl.count / (EXTRACT(EPOCH FROM (NOW() - published_at)) / 3600 / 24), 0) as popularity_score, article_save_id, article_save_url
FROM omnivore.omnivore.discover_feed_articles
FROM omnivore.discover_feed_articles
LEFT JOIN (SELECT discover_article_id as article_id, count(*) as count FROM omnivore.discover_feed_save_link group by discover_article_id) sl on id=sl.article_id
LEFT JOIN (SELECT discover_article_id, article_save_id, article_save_url FROM omnivore.discover_feed_save_link WHERE user_id=$1 and deleted = false) su on id=su.discover_article_id
WHERE COALESCE(sl.count / (EXTRACT(EPOCH FROM (NOW() - published_at)) / 3600 / 24), 0) > 0.0
@ -56,7 +54,6 @@ const getPopularTopics = (
}
const getAllTopics = (
queryRunner: QueryRunner,
uid: string,
after: string,
amt: number,
@ -66,10 +63,10 @@ const getAllTopics = (
if (feedId) {
params.push(feedId)
}
return queryRunner.query(
return appDataSource.query(
`
SELECT id, title, feed_id as feed, slug, description, url, author, image, published_at, article_save_id, article_save_url
FROM omnivore.omnivore.discover_feed_articles
FROM omnivore.discover_feed_articles
LEFT JOIN (SELECT discover_article_id, article_save_id, article_save_url FROM omnivore.discover_feed_save_link WHERE user_id=$1 and deleted = false) su on id=su.discover_article_id
WHERE (feed_id in (SELECT feed_id FROM omnivore.discover_feed_subscription WHERE user_id = $1) OR feed_id = '${COMMUNITY_FEED_ID}')
${feedId != null ? `AND feed_id = $4` : ''}
@ -81,7 +78,6 @@ const getAllTopics = (
}
const getTopicInformation = (
queryRunner: QueryRunner,
discoverTopicId: string,
uid: string,
after: string,
@ -92,7 +88,7 @@ const getTopicInformation = (
if (feedId) {
params.push(feedId)
}
return queryRunner.query(
return appDataSource.query(
`SELECT id, title, feed_id as feed, slug, description, url, author, image, published_at, article_save_id, article_save_url
FROM omnivore.discover_feed_articles
INNER JOIN (SELECT discover_feed_article_id FROM omnivore.discover_feed_article_topic_link WHERE discover_topic_name=$2) topic on topic.discover_feed_article_id=id
@ -115,11 +111,7 @@ export const getDiscoverFeedArticlesResolver = authorized<
const startCursor: string = after || ''
const firstAmnt = Math.min(first || 10, 100) // limit to 100 items
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
const { rows: topics } = (await queryRunner.query(
const { rows: topics } = (await appDataSource.query(
`SELECT * FROM "omnivore"."discover_topics" WHERE "name" = $1`,
[discoverTopicId]
)) as { rows: unknown[] }
@ -134,7 +126,6 @@ export const getDiscoverFeedArticlesResolver = authorized<
let discoverArticles: DiscoverFeedArticleDBRows = { rows: [] }
if (discoverTopicId === 'Popular') {
discoverArticles = await getPopularTopics(
queryRunner,
uid,
startCursor,
firstAmnt,
@ -142,7 +133,6 @@ export const getDiscoverFeedArticlesResolver = authorized<
)
} else if (discoverTopicId === 'All') {
discoverArticles = await getAllTopics(
queryRunner,
uid,
startCursor,
firstAmnt,
@ -150,7 +140,6 @@ export const getDiscoverFeedArticlesResolver = authorized<
)
} else {
discoverArticles = await getTopicInformation(
queryRunner,
discoverTopicId,
uid,
startCursor,
@ -159,8 +148,6 @@ export const getDiscoverFeedArticlesResolver = authorized<
)
}
await queryRunner.release()
return {
__typename: 'GetDiscoverFeedArticleSuccess',
discoverArticles: discoverArticles.rows.slice(0, firstAmnt).map((it) => ({

View File

@ -1,12 +1,11 @@
import { authorized } from '../../utils/gql-utils'
import { appDataSource } from '../../data_source'
import {
DeleteDiscoverFeedError,
DeleteDiscoverFeedErrorCode,
DeleteDiscoverFeedSuccess,
MutationDeleteDiscoverFeedArgs,
} from '../../generated/graphql'
import { appDataSource } from '../../data_source'
import { QueryRunner } from 'typeorm'
import { authorized } from '../../utils/gql-utils'
export const deleteDiscoverFeedsResolver = authorized<
DeleteDiscoverFeedSuccess,
@ -14,12 +13,8 @@ export const deleteDiscoverFeedsResolver = authorized<
MutationDeleteDiscoverFeedArgs
>(async (_, { input: { feedId } }, { uid, log }) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
// Ensure that it actually exists for the user.
const feeds = (await queryRunner.query(
const feeds = (await appDataSource.query(
`SELECT * FROM omnivore.discover_feed_subscription sub
WHERE sub.user_id = $1 and sub.feed_id = $2`,
[uid, feedId]
@ -36,13 +31,12 @@ export const deleteDiscoverFeedsResolver = authorized<
}
}
await queryRunner.query(
await appDataSource.query(
`DELETE FROM omnivore.discover_feed_subscription sub
WHERE sub.user_id = $1 and sub.feed_id = $2`,
[uid, feedId]
)
await queryRunner.release()
return {
__typename: 'DeleteDiscoverFeedSuccess',
id: feedId,

View File

@ -1,12 +1,11 @@
import { authorized } from '../../utils/gql-utils'
import { appDataSource } from '../../data_source'
import {
EditDiscoverFeedError,
EditDiscoverFeedErrorCode,
EditDiscoverFeedSuccess,
MutationEditDiscoverFeedArgs,
} from '../../generated/graphql'
import { appDataSource } from '../../data_source'
import { QueryRunner } from 'typeorm'
import { authorized } from '../../utils/gql-utils'
export const editDiscoverFeedsResolver = authorized<
EditDiscoverFeedSuccess,
@ -14,12 +13,8 @@ export const editDiscoverFeedsResolver = authorized<
MutationEditDiscoverFeedArgs
>(async (_, { input: { feedId, name } }, { uid, log }) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
// Ensure that it actually exists for the user.
const feeds = (await queryRunner.query(
const feeds = (await appDataSource.query(
`SELECT * FROM omnivore.discover_feed_subscription sub
WHERE sub.user_id = $1 and sub.feed_id = $2`,
[uid, feedId]
@ -36,13 +31,12 @@ export const editDiscoverFeedsResolver = authorized<
}
}
await queryRunner.query(
await appDataSource.query(
`UPDATE omnivore.discover_feed_subscription SET visible_name = $1
WHERE user_id = $2 and feed_id = $3`,
[name, uid, feedId]
)
await queryRunner.release()
return {
__typename: 'EditDiscoverFeedSuccess',
id: feedId,

View File

@ -1,23 +1,18 @@
import { authorized } from '../../utils/gql-utils'
import { appDataSource } from '../../data_source'
import {
DiscoverFeed,
DiscoverFeedError,
DiscoverFeedErrorCode,
DiscoverFeedSuccess,
} from '../../generated/graphql'
import { appDataSource } from '../../data_source'
import { QueryRunner } from 'typeorm'
import { authorized } from '../../utils/gql-utils'
export const getDiscoverFeedsResolver = authorized<
DiscoverFeedSuccess,
DiscoverFeedError
>(async (_, _args, { uid, log }) => {
try {
const queryRunner = (await appDataSource
.createQueryRunner()
.connect()) as QueryRunner
const existingFeed = (await queryRunner.query(
const existingFeed = (await appDataSource.query(
`SELECT *, COALESCE(visible_name, title) as "visibleName" FROM omnivore.discover_feed_subscription sub
INNER JOIN omnivore.discover_feed feed on sub.feed_id=id
WHERE sub.user_id = $1`,
@ -26,7 +21,6 @@ export const getDiscoverFeedsResolver = authorized<
rows: DiscoverFeed[]
}
await queryRunner.release()
return {
__typename: 'DiscoverFeedSuccess',
feeds: existingFeed.rows || [],