stress test
This commit is contained in:
@@ -51,7 +51,10 @@ async function fetchHandler(
|
|||||||
|
|
||||||
const res = await fetch(reqUri, {
|
const res = await fetch(reqUri, {
|
||||||
method: reqMethod,
|
method: reqMethod,
|
||||||
headers: reqHeaders,
|
headers: {
|
||||||
|
...reqHeaders,
|
||||||
|
'x-bsky-entryway': 'short-session'
|
||||||
|
},
|
||||||
body: reqBody,
|
body: reqBody,
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +1,69 @@
|
|||||||
|
import {BskyAgent, jsonToLex, stringifyLex} from '@atproto/api'
|
||||||
|
|
||||||
|
const GET_TIMEOUT = 15e3 // 15s
|
||||||
|
const POST_TIMEOUT = 60e3 // 60s
|
||||||
|
|
||||||
export function doPolyfill() {
|
export function doPolyfill() {
|
||||||
// no polyfill is needed on web
|
BskyAgent.configure({fetch: fetchHandler})
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FetchHandlerResponse {
|
||||||
|
status: number
|
||||||
|
headers: Record<string, string>
|
||||||
|
body: any
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchHandler(
|
||||||
|
reqUri: string,
|
||||||
|
reqMethod: string,
|
||||||
|
reqHeaders: Record<string, string>,
|
||||||
|
reqBody: any,
|
||||||
|
): Promise<FetchHandlerResponse> {
|
||||||
|
const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type']
|
||||||
|
if (reqMimeType && reqMimeType.startsWith('application/json')) {
|
||||||
|
reqBody = stringifyLex(reqBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
const controller = new AbortController()
|
||||||
|
const to = setTimeout(
|
||||||
|
() => controller.abort(),
|
||||||
|
reqMethod === 'post' ? POST_TIMEOUT : GET_TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await fetch(reqUri, {
|
||||||
|
method: reqMethod,
|
||||||
|
headers: {
|
||||||
|
...reqHeaders,
|
||||||
|
'x-bsky-entryway': 'short-session'
|
||||||
|
},
|
||||||
|
body: reqBody,
|
||||||
|
signal: controller.signal,
|
||||||
|
})
|
||||||
|
|
||||||
|
const resStatus = res.status
|
||||||
|
const resHeaders: Record<string, string> = {}
|
||||||
|
res.headers.forEach((value: string, key: string) => {
|
||||||
|
resHeaders[key] = value
|
||||||
|
})
|
||||||
|
const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type']
|
||||||
|
let resBody
|
||||||
|
if (resMimeType) {
|
||||||
|
if (resMimeType.startsWith('application/json')) {
|
||||||
|
resBody = jsonToLex(await res.json())
|
||||||
|
} else if (resMimeType.startsWith('text/')) {
|
||||||
|
resBody = await res.text()
|
||||||
|
} else if (resMimeType === 'application/vnd.ipld.car') {
|
||||||
|
resBody = await res.arrayBuffer()
|
||||||
|
} else {
|
||||||
|
throw new Error('Non-supported mime type')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(to)
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: resStatus,
|
||||||
|
headers: resHeaders,
|
||||||
|
body: resBody,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-15
@@ -35,7 +35,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) {
|
|||||||
const aggregatedStats = React.useRef<AggregatedStats | null>(null)
|
const aggregatedStats = React.useRef<AggregatedStats | null>(null)
|
||||||
const throttledFlushAggregatedStats = React.useMemo(
|
const throttledFlushAggregatedStats = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
throttle(() => flushToStatsig(aggregatedStats.current), 45e3, {
|
throttle(() => flushToStatsig(aggregatedStats.current), 5e3, {
|
||||||
leading: true, // The outer call is already throttled somewhat.
|
leading: true, // The outer call is already throttled somewhat.
|
||||||
trailing: true,
|
trailing: true,
|
||||||
}),
|
}),
|
||||||
@@ -43,22 +43,41 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const sendToFeedNoDelay = React.useCallback(() => {
|
const sendToFeedNoDelay = React.useCallback(() => {
|
||||||
const proxyAgent = agent.withProxy(
|
|
||||||
// @ts-ignore TODO need to update withProxy() to support this key -prf
|
|
||||||
'bsky_fg',
|
|
||||||
// TODO when we start sending to other feeds, we need to grab their DID -prf
|
|
||||||
'did:web:discover.bsky.app',
|
|
||||||
) as BskyAgent
|
|
||||||
|
|
||||||
const interactions = Array.from(queue.current).map(toInteraction)
|
const interactions = Array.from(queue.current).map(toInteraction)
|
||||||
queue.current.clear()
|
queue.current.clear()
|
||||||
|
|
||||||
// Send to the feed
|
if (true) {
|
||||||
proxyAgent.app.bsky.feed
|
// Send to the feed
|
||||||
.sendInteractions({interactions})
|
agent.app.bsky.feed
|
||||||
.catch((e: any) => {
|
.sendInteractions({ interactions }, {
|
||||||
logger.warn('Failed to send feed interactions', {error: e})
|
encoding: 'application/json',
|
||||||
})
|
headers: {
|
||||||
|
'atproto-proxy': 'did:web:discover.bsky.app#bsky_fg'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e: any) => {
|
||||||
|
logger.warn('Failed to send feed interactions', { error: e })
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const proxyAgent = agent.withProxy(
|
||||||
|
// @ts-ignore TODO need to update withProxy() to support this key -prf
|
||||||
|
'bsky_fg',
|
||||||
|
// TODO when we start sending to other feeds, we need to grab their DID -prf
|
||||||
|
'did:web:discover.bsky.app',
|
||||||
|
) as BskyAgent
|
||||||
|
|
||||||
|
// Send to the feed
|
||||||
|
proxyAgent.app.bsky.feed
|
||||||
|
.sendInteractions({ interactions }, {
|
||||||
|
encoding: 'application/json',
|
||||||
|
headers: {
|
||||||
|
'atproto-proxy': 'did:web:discover.bsky.app#bsky_fg'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e: any) => {
|
||||||
|
logger.warn('Failed to send feed interactions', { error: e })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Send to Statsig
|
// Send to Statsig
|
||||||
if (aggregatedStats.current === null) {
|
if (aggregatedStats.current === null) {
|
||||||
@@ -70,7 +89,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) {
|
|||||||
|
|
||||||
const sendToFeed = React.useMemo(
|
const sendToFeed = React.useMemo(
|
||||||
() =>
|
() =>
|
||||||
throttle(sendToFeedNoDelay, 15e3, {
|
throttle(sendToFeedNoDelay, 1e3, {
|
||||||
leading: false,
|
leading: false,
|
||||||
trailing: true,
|
trailing: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ let nextMessageIndex = 0
|
|||||||
const MAX_SLICE_LENGTH = 1000
|
const MAX_SLICE_LENGTH = 1000
|
||||||
|
|
||||||
export function addSessionDebugLog(log: Log) {
|
export function addSessionDebugLog(log: Log) {
|
||||||
|
console.log(new Date(), log)
|
||||||
try {
|
try {
|
||||||
if (!Statsig.initializeCalled() || !Statsig.getStableID()) {
|
if (!Statsig.initializeCalled() || !Statsig.getStableID()) {
|
||||||
// Drop these logs for now.
|
// Drop these logs for now.
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export type ListProps<ItemT> = Omit<
|
|||||||
}
|
}
|
||||||
export type ListRef = React.MutableRefObject<any | null> // TODO: Better types.
|
export type ListRef = React.MutableRefObject<any | null> // TODO: Better types.
|
||||||
|
|
||||||
const ON_ITEM_SEEN_WAIT_DURATION = 1.5e3 // when we consider post to be "seen"
|
const ON_ITEM_SEEN_WAIT_DURATION = 100 // when we consider post to be "seen"
|
||||||
const ON_ITEM_SEEN_INTERSECTION_OPTS = {
|
const ON_ITEM_SEEN_INTERSECTION_OPTS = {
|
||||||
rootMargin: '-200px 0px -200px 0px',
|
rootMargin: '-200px 0px -200px 0px',
|
||||||
} // post must be 200px visible to be "seen"
|
} // post must be 200px visible to be "seen"
|
||||||
|
|||||||
Reference in New Issue
Block a user