Skip to content

Commit 2fe4bad

Browse files
committed
feat(notion): add rate limit support and process documents concurrently
1 parent 7c77cef commit 2fe4bad

File tree

7 files changed

+93
-38
lines changed

7 files changed

+93
-38
lines changed
Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,13 @@
11
import { makeSource, defineDatabase } from 'contentlayer-source-notion'
2-
import * as notion from '@notionhq/client'
32

4-
const client = new notion.Client({
5-
auth: process.env.NOTION_TOKEN,
6-
})
7-
8-
const Category = defineDatabase(() => ({
9-
name: 'Category',
10-
databaseId: '8bf1821701f14ab8bbbfaad0309ed09c',
11-
importContent: false,
12-
}))
13-
14-
const Post = defineDatabase(() => ({
3+
export const Post = defineDatabase(() => ({
154
name: 'Post',
165
databaseId: 'fe26b972ec3f4b32a1882230915fe111',
17-
properties: {
18-
email: {
19-
name: 'Email',
20-
required: true,
21-
},
22-
category: {
23-
type: 'relation',
24-
name: 'Category',
25-
relation: Category,
26-
single: true,
27-
},
28-
},
29-
computedFields: {
30-
slug: {
31-
type: 'string',
32-
resolve: (_) => 'test',
33-
},
34-
},
356
}))
367

378
export default makeSource({
38-
client,
39-
databaseTypes: [Post, Category],
9+
clientOptions: {
10+
auth: process.env.NOTION_TOKEN,
11+
},
12+
databaseTypes: [Post],
4013
})

packages/@contentlayer/source-notion/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"@notion-render/client": "1.0.0-rc.1",
2323
"@notionhq/client": "^2.2.3",
2424
"contentful-management": "7.22.4",
25+
"p-queue": "^7.3.4",
26+
"p-retry": "^5.1.2",
2527
"slugify": "^1.6.5"
2628
}
2729
}

packages/@contentlayer/source-notion/src/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { NotionRenderer } from '@notion-render/client'
55
import * as notion from '@notionhq/client'
66

77
import { fetchAllDocuments } from './fetchData/fetchAllDocuments.js'
8+
import { fetchNotion } from './notion/fetchNotion.js'
89
import { provideSchema } from './schema/provideSchema.js'
910
import { flattendDatabaseTypeDef } from './schema/utils/flattenDatabaseTypeDef.js'
1011
import { NotionClient, NotionRenderer as NotionRendererTag } from './services.js'
@@ -23,8 +24,11 @@ export const makeSource: core.MakeSourcePlugin<PluginOptions & core.PartialArgs>
2324
_.def(),
2425
)
2526

26-
const client = rest.client ?? new notion.Client()
27-
const renderer = rest.renderer ?? new NotionRenderer({ client })
27+
const client = new notion.Client({
28+
fetch: fetchNotion,
29+
...rest.clientOptions,
30+
})
31+
const renderer = new NotionRenderer({ client, ...rest.rendererOptions })
2832

2933
return {
3034
type: 'notion',

packages/@contentlayer/source-notion/src/notion/fetchDatabasePages.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ export const fetchDatabasePages = ({ databaseTypeDef }: FetchDatabasePagesArgs)
1515
S.service(NotionClient),
1616
S.chain((client) =>
1717
S.async<unknown, unknown, PageObjectResponse[]>(async (emit) => {
18-
let nextCursor = undefined
18+
let nextCursor: string | undefined = undefined
19+
console.log(`Querying pages for ${databaseTypeDef.name}`)
1920

2021
do {
22+
console.log(`Querying pages for ${databaseTypeDef.name} with cursor ${nextCursor}`)
2123
const res = await client.databases.query({
2224
database_id: databaseTypeDef.databaseId,
25+
start_cursor: nextCursor ?? undefined,
2326
filter: databaseTypeDef.query?.filter,
2427
sorts: databaseTypeDef.query?.sorts,
2528
})
2629

27-
nextCursor = res.next_cursor
30+
console.log(`Found ${res.results.length} pages`)
31+
nextCursor = res.next_cursor as string | undefined // NOTE: Throw type error and make res any if not typed, why???
2832
emit.single(res.results as PageObjectResponse[])
2933
} while (nextCursor)
3034

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import PQueue from 'p-queue'
2+
import pRetry from 'p-retry'
3+
4+
const queue = new PQueue({ interval: 1000, intervalCap: 4 })
5+
6+
export const fetchNotion = (...args: Parameters<typeof fetch>) => {
7+
return queue.add(() =>
8+
pRetry(
9+
() => {
10+
console.log(`Fetching ${args[0]}`)
11+
return fetch(...args)
12+
},
13+
{
14+
retries: 5,
15+
onFailedAttempt: async (r) => {
16+
console.warn(`WARN: Error while querying Notion, retry #${r.attemptNumber}`)
17+
await new Promise((res) => setTimeout(res, 1000))
18+
},
19+
},
20+
),
21+
) as Promise<Response>
22+
}

packages/@contentlayer/source-notion/src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import type * as notion from '@notionhq/client'
55
import type { DatabaseTypes } from './schema/types/database.js'
66

77
export type PluginOptions = {
8-
client?: notion.Client
9-
renderer?: NotionRenderer
8+
clientOptions?: ConstructorParameters<typeof notion.Client>[0]
9+
rendererOptions?: ConstructorParameters<typeof NotionRenderer>[0]
1010
databaseTypes: DatabaseTypes
1111
}
1212

yarn.lock

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,13 @@ __metadata:
17921792
languageName: node
17931793
linkType: hard
17941794

1795+
"@types/retry@npm:0.12.1":
1796+
version: 0.12.1
1797+
resolution: "@types/retry@npm:0.12.1"
1798+
checksum: 5f46b2556053655f78262bb33040dc58417c900457cc63ff37d6c35349814471453ef511af0cec76a540c601296cd2b22f64bab1ab649c0dacc0223765ba876c
1799+
languageName: node
1800+
linkType: hard
1801+
17951802
"@types/scheduler@npm:*":
17961803
version: 0.16.2
17971804
resolution: "@types/scheduler@npm:0.16.2"
@@ -3032,6 +3039,8 @@ __metadata:
30323039
"@notionhq/client": ^2.2.3
30333040
"@types/node": ^18.13.0
30343041
contentful-management: 7.22.4
3042+
p-queue: ^7.3.4
3043+
p-retry: ^5.1.2
30353044
slugify: ^1.6.5
30363045
languageName: unknown
30373046
linkType: soft
@@ -3898,6 +3907,13 @@ __metadata:
38983907
languageName: node
38993908
linkType: hard
39003909

3910+
"eventemitter3@npm:^4.0.7":
3911+
version: 4.0.7
3912+
resolution: "eventemitter3@npm:4.0.7"
3913+
checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374
3914+
languageName: node
3915+
linkType: hard
3916+
39013917
"execa@npm:^0.7.0":
39023918
version: 0.7.0
39033919
resolution: "execa@npm:0.7.0"
@@ -6888,13 +6904,40 @@ __metadata:
68886904
languageName: node
68896905
linkType: hard
68906906

6907+
"p-queue@npm:^7.3.4":
6908+
version: 7.3.4
6909+
resolution: "p-queue@npm:7.3.4"
6910+
dependencies:
6911+
eventemitter3: ^4.0.7
6912+
p-timeout: ^5.0.2
6913+
checksum: a21b8a4dd75f64a4988e4468cc344d1b45132506ddd2c771932d3de446d108ee68713b629e0d3f0809c227bc10eafc613edde6ae741d9f60db89b6031e40921c
6914+
languageName: node
6915+
linkType: hard
6916+
6917+
"p-retry@npm:^5.1.2":
6918+
version: 5.1.2
6919+
resolution: "p-retry@npm:5.1.2"
6920+
dependencies:
6921+
"@types/retry": 0.12.1
6922+
retry: ^0.13.1
6923+
checksum: f063c08b1adc3cf7c01de01eb2dbda841970229f9f229c5167ebf4e2080d8a38b1f4e6eccefac74bca97cfaf4436d0a0eeb0b551175b26bc8b3116195f61bba8
6924+
languageName: node
6925+
linkType: hard
6926+
68916927
"p-throttle@npm:^4.1.1":
68926928
version: 4.1.1
68936929
resolution: "p-throttle@npm:4.1.1"
68946930
checksum: fe8709f3c3b1da7c033479375c2c302e80c1a5d86449013afa7cd46d1dc210bc824a7e4a9d088e66d31987d00878c2b5491bb2fe76246d4d2fc9a1636f5f8298
68956931
languageName: node
68966932
linkType: hard
68976933

6934+
"p-timeout@npm:^5.0.2":
6935+
version: 5.1.0
6936+
resolution: "p-timeout@npm:5.1.0"
6937+
checksum: f5cd4e17301ff1ff1d8dbf2817df0ad88c6bba99349fc24d8d181827176ad4f8aca649190b8a5b1a428dfd6ddc091af4606835d3e0cb0656e04045da5c9e270c
6938+
languageName: node
6939+
linkType: hard
6940+
68986941
"p-try@npm:^2.0.0":
68996942
version: 2.2.0
69006943
resolution: "p-try@npm:2.2.0"
@@ -7557,6 +7600,13 @@ __metadata:
75577600
languageName: node
75587601
linkType: hard
75597602

7603+
"retry@npm:^0.13.1":
7604+
version: 0.13.1
7605+
resolution: "retry@npm:0.13.1"
7606+
checksum: 47c4d5be674f7c13eee4cfe927345023972197dbbdfba5d3af7e461d13b44de1bfd663bfc80d2f601f8ef3fc8164c16dd99655a221921954a65d044a2fc1233b
7607+
languageName: node
7608+
linkType: hard
7609+
75607610
"reusify@npm:^1.0.4":
75617611
version: 1.0.4
75627612
resolution: "reusify@npm:1.0.4"

0 commit comments

Comments
 (0)