resolve conflicts

This commit is contained in:
Hongbo Wu 2023-03-22 15:13:48 +08:00
parent ef800ded81
commit c07ada0218
9 changed files with 64 additions and 127 deletions

View file

@ -72,6 +72,7 @@ import {
UpdatesSinceSuccess,
} from '../../generated/graphql'
import { createPageSaveRequest } from '../../services/create_page_save_request'
import { createLabels } from '../../services/labels'
import { parsedContentToPage } from '../../services/save_page'
import { traceAs } from '../../tracing'
import { Merge } from '../../util'
@ -101,7 +102,6 @@ import {
makeStorageFilePublic,
} from '../../utils/uploads'
import { WithDataSourcesContext } from '../types'
import { createLabels } from '../../services/labels'
enum ArticleFormat {
Markdown = 'markdown',

View file

@ -1,5 +1,7 @@
/* eslint-disable prefer-const */
import { getPageByParam } from '../../elastic/pages'
import { User } from '../../entity/user'
import { getRepository } from '../../entity/utils'
import { env } from '../../env'
import {
ArticleSavingRequestError,
@ -60,11 +62,14 @@ export const articleSavingRequestResolver = authorized<
ArticleSavingRequestSuccess,
ArticleSavingRequestError,
QueryArticleSavingRequestArgs
>(async (_, { id, url }, { models, claims }) => {
>(async (_, { id, url }, { claims }) => {
if (!id && !url) {
return { errorCodes: [ArticleSavingRequestErrorCode.BadData] }
}
const user = await models.user.get(claims.uid)
const user = await getRepository(User).findOne({
where: { id: claims.uid },
relations: ['profile'],
})
if (!user) {
return { errorCodes: [ArticleSavingRequestErrorCode.Unauthorized] }
}

View file

@ -4,7 +4,6 @@ import { htmlToSpeechFile } from '@omnivore/text-to-speech-handler'
import cors from 'cors'
import express from 'express'
import * as jwt from 'jsonwebtoken'
import { kx } from '../datalayer/knex_config'
import { createPubSubClient } from '../datalayer/pubsub'
import { getPageById, updatePage } from '../elastic/pages'
import { Speech, SpeechState } from '../entity/speech'
@ -12,7 +11,6 @@ import { getRepository } from '../entity/utils'
import { env } from '../env'
import { CreateArticleErrorCode } from '../generated/graphql'
import { Claims } from '../resolvers/types'
import { initModels } from '../server'
import { createPageSaveRequest } from '../services/create_page_save_request'
import { getClaimsByToken } from '../utils/auth'
import { isSiteBlockedForParse } from '../utils/blocked'

View file

@ -2,19 +2,19 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import express from 'express'
import { DateTime } from 'luxon'
import { v4 as uuidv4 } from 'uuid'
import { EntityType, readPushSubscription } from '../../datalayer/pubsub'
import { getPageById, searchPages } from '../../elastic/pages'
import { Page } from '../../elastic/types'
import { Integration, IntegrationType } from '../../entity/integration'
import { getRepository } from '../../entity/utils'
import { syncWithIntegration } from '../../services/integrations'
import { Claims } from '../../resolvers/types'
import { getIntegrationService } from '../../services/integrations'
import { getClaimsByToken } from '../../utils/auth'
import { buildLogger } from '../../utils/logger'
import { DateFilter } from '../../utils/search'
import { DateTime } from 'luxon'
import { createGCSFile } from '../../utils/uploads'
import { v4 as uuidv4 } from 'uuid'
import { getClaimsByToken } from '../../utils/auth'
import { Claims } from '../../resolvers/types'
export interface Message {
type?: EntityType

View file

@ -9,17 +9,14 @@ import {
updatePage,
} from '../elastic/pages'
import { ArticleSavingRequestStatus, Label, PageType } from '../elastic/types'
import { User } from '../entity/user'
import { getRepository } from '../entity/utils'
import {
ArticleSavingRequest,
CreateArticleSavingRequestErrorCode,
} from '../generated/graphql'
// TODO: switch to a proper Entity instead of using the old data models.
import { DataModels } from '../resolvers/types'
import { enqueueParseRequest } from '../utils/createTask'
import { generateSlug, pageToArticleSavingRequest } from '../utils/helpers'
import * as privateIpLib from 'private-ip'
import { getRepository } from '../entity/utils'
import { User } from '../entity/user'
interface PageSaveRequest {
userId: string
@ -157,7 +154,14 @@ export const createPageSaveRequest = async ({
)
}
// enqueue task to parse page
await enqueueParseRequest(url, userId, page.id, priority)
await enqueueParseRequest({
url,
userId,
saveRequestId: page.id,
priority,
archivedAt,
labels,
})
return pageToArticleSavingRequest(user, page)
}

View file

@ -109,10 +109,10 @@ export const savePage = async (
url: articleToSave.url,
})
// save state
const archivedAt =
articleToSave.archivedAt =
input.state === ArticleSavingRequestStatus.Archived ? new Date() : null
// add labels to page
const labels = input.labels
articleToSave.labels = input.labels
? await createLabels(ctx, input.labels)
: undefined
@ -125,11 +125,9 @@ export const savePage = async (
{
// update the page with the new content
...articleToSave,
archivedAt, // unarchive if it was archived
id: pageId, // we don't want to update the id
slug, // we don't want to update the slug
createdAt: existingPage.createdAt, // we don't want to update the createdAt
labels,
},
ctx
))
@ -146,8 +144,8 @@ export const savePage = async (
url: articleToSave.url,
pubsub: ctx.pubsub,
articleSavingRequestId: input.clientRequestId,
archivedAt,
labels,
archivedAt: articleToSave.archivedAt,
labels: articleToSave.labels,
})
} catch (e) {
return {
@ -156,14 +154,7 @@ export const savePage = async (
}
}
} else {
const newPageId = await createPage(
{
...articleToSave,
archivedAt,
labels,
},
ctx
)
const newPageId = await createPage(articleToSave, ctx)
if (!newPageId) {
return {
errorCodes: [SaveErrorCode.Unknown],

View file

@ -2,14 +2,14 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */
// Imports the Google Cloud Tasks library.
import { CloudTasksClient, protos } from '@google-cloud/tasks'
import { google } from '@google-cloud/tasks/build/protos/protos'
import axios from 'axios'
import { nanoid } from 'nanoid'
import { Label, Recommendation } from '../elastic/types'
import { env } from '../env'
import { signFeatureToken } from '../services/features'
import { CreateTaskError } from './errors'
import { buildLogger } from './logger'
import { nanoid } from 'nanoid'
import { google } from '@google-cloud/tasks/build/protos/protos'
import { signFeatureToken } from '../services/features'
import { Recommendation } from '../elastic/types'
import View = google.cloud.tasks.v2.Task.View
const logger = buildLogger('app.dispatch')
@ -194,18 +194,30 @@ export const deleteTask = async (
* @param queue - Queue name
* @returns Name of the task created
*/
export const enqueueParseRequest = async (
url: string,
userId: string,
saveRequestId: string,
priority: 'low' | 'high' = 'high',
queue = env.queue.name
): Promise<string> => {
export const enqueueParseRequest = async ({
url,
userId,
saveRequestId,
priority = 'high',
queue = env.queue.name,
archivedAt,
labels,
}: {
url: string
userId: string
saveRequestId: string
priority?: 'low' | 'high'
queue?: string
archivedAt?: Date | null
labels?: Label[]
}): Promise<string> => {
const { GOOGLE_CLOUD_PROJECT } = process.env
const payload = {
url,
userId,
saveRequestId,
archivedAt,
labels,
}
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
@ -245,79 +257,6 @@ export const enqueueParseRequest = async (
return createdTasks[0].name
}
export const enqueueReminder = async (
userId: string,
scheduleTime: number
): Promise<string> => {
const { GOOGLE_CLOUD_PROJECT } = process.env
const payload = {
userId,
scheduleTime,
}
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
return nanoid()
}
const createdTasks = await createHttpTaskWithToken({
project: GOOGLE_CLOUD_PROJECT,
payload,
scheduleTime,
taskHandlerUrl: env.queue.reminderTaskHandlerUrl,
})
if (!createdTasks || !createdTasks[0].name) {
logger.error(`Unable to get the name of the task`, {
payload,
createdTasks,
})
throw new CreateTaskError(`Unable to get the name of the task`)
}
return createdTasks[0].name
}
export const enqueueSyncWithIntegration = async (
userId: string,
integrationName: string
): Promise<string> => {
const { GOOGLE_CLOUD_PROJECT, PUBSUB_VERIFICATION_TOKEN } = process.env
// use pubsub data format to send the userId to the task handler
const payload = {
message: {
data: Buffer.from(
JSON.stringify({
userId,
})
).toString('base64'),
publishTime: new Date().toISOString(),
},
}
// If there is no Google Cloud Project Id exposed, it means that we are in local environment
if (env.dev.isLocal || !GOOGLE_CLOUD_PROJECT) {
return nanoid()
}
const createdTasks = await createHttpTaskWithToken({
project: GOOGLE_CLOUD_PROJECT,
payload,
taskHandlerUrl: `${
env.queue.integrationTaskHandlerUrl
}/${integrationName.toLowerCase()}/sync_all?token=${PUBSUB_VERIFICATION_TOKEN}`,
priority: 'low',
})
if (!createdTasks || !createdTasks[0].name) {
logger.error(`Unable to get the name of the task`, {
payload,
createdTasks,
})
throw new CreateTaskError(`Unable to get the name of the task`)
}
return createdTasks[0].name
}
export const enqueueTextToSpeech = async ({
userId,
text,

View file

@ -1,4 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import crypto from 'crypto'
import normalizeUrl from 'normalize-url'
import path from 'path'
import _ from 'underscore'
import slugify from 'voca/slugify'
import wordsCounter from 'word-counting'
import { RegistrationType, UserData } from '../datalayer/user/model'
import { updatePage } from '../elastic/pages'
import { ArticleSavingRequestStatus, Page } from '../elastic/types'
import { User } from '../entity/user'
import {
ArticleSavingRequest,
CreateArticleError,
@ -6,19 +16,9 @@ import {
Profile,
ResolverFn,
} from '../generated/graphql'
import { Claims, WithDataSourcesContext } from '../resolvers/types'
import { RegistrationType, UserData } from '../datalayer/user/model'
import crypto from 'crypto'
import slugify from 'voca/slugify'
import { Merge } from '../util'
import { CreateArticlesSuccessPartial } from '../resolvers'
import { ArticleSavingRequestStatus, Page } from '../elastic/types'
import { updatePage } from '../elastic/pages'
import path from 'path'
import normalizeUrl from 'normalize-url'
import wordsCounter from 'word-counting'
import _ from 'underscore'
import { User } from '../entity/user'
import { Claims, WithDataSourcesContext } from '../resolvers/types'
import { Merge } from '../util'
interface InputObject {
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View file

@ -7,5 +7,5 @@
"outDir": "dist"
},
"include": ["src", "test"],
"exclude": ["./src/generated"]
"exclude": ["./src/generated", "./test"]
}