This commit is contained in:
Hailey
2025-08-31 15:49:08 -07:00
parent 976a2519a7
commit d7bd7cd52f
2 changed files with 26 additions and 23 deletions
+20 -19
View File
@@ -3,6 +3,7 @@ import {
CredentialSession, CredentialSession,
type ToolsOzoneSafelinkQueryEvents, type ToolsOzoneSafelinkQueryEvents,
} from '@atproto/api' } from '@atproto/api'
import {HOUR} from '@atproto/common'
import {LRUCache} from 'lru-cache' import {LRUCache} from 'lru-cache'
import {type ServiceConfig} from '../config.js' import {type ServiceConfig} from '../config.js'
@@ -57,7 +58,7 @@ export class SafelinkClient {
} }
const urlRule = this.urlCache.get(url) const urlRule = this.urlCache.get(url)
if (urlRule) { if (urlRule && urlRule !== 'ok') {
return urlRule return urlRule
} }
@@ -90,11 +91,12 @@ export class SafelinkClient {
url: string, url: string,
pattern: RulePatternType, pattern: RulePatternType,
): Promise<SafelinkRule> { ): Promise<SafelinkRule> {
// @ts-ignore
return db.db return db.db
.selectFrom('safelink_rule') .selectFrom('safelink_rule')
.selectAll()
.where('url', '=', url) .where('url', '=', url)
.where('pattern', '=', pattern) .where('pattern', '=', pattern)
.orderBy('createdAt', 'desc')
.executeTakeFirstOrThrow() .executeTakeFirstOrThrow()
} }
@@ -125,9 +127,9 @@ export class SafelinkClient {
}) })
if (rule.pattern === 'domain') { if (rule.pattern === 'domain') {
this.domainCache.set(rule.url, rule) this.domainCache.delete(rule.url)
} else { } else {
this.urlCache.set(rule.url, rule) this.urlCache.delete(rule.url)
} }
} }
@@ -181,6 +183,7 @@ export class SafelinkClient {
res = await agent.tools.ozone.safelink.queryEvents({ res = await agent.tools.ozone.safelink.queryEvents({
cursor, cursor,
limit: 100, limit: 100,
sortDirection: 'asc',
}) })
} catch (err) { } catch (err) {
redirectLogger.error( redirectLogger.error(
@@ -191,15 +194,13 @@ export class SafelinkClient {
return return
} }
if (res.data.cursor === this.cursor || res.data.events.length === 0) { if (res.data.events.length === 0) {
redirectLogger.info( redirectLogger.info('received no new safelink events from ozone')
{cursor: res.data.cursor},
'received same cursor from Ozone',
)
setTimeout(() => this.runFetchEvents(), SAFELINK_MAX_FETCH_INTERVAL) setTimeout(() => this.runFetchEvents(), SAFELINK_MAX_FETCH_INTERVAL)
} else { } else {
await this.db.transaction(async db => { await this.db.transaction(async db => {
for (const rule of res.data.events) { for (const rule of res.data.events) {
redirectLogger.info(rule.id)
if (rule.eventType === 'removeRule') { if (rule.eventType === 'removeRule') {
await this.removeRule(db, rule) await this.removeRule(db, rule)
} else { } else {
@@ -210,7 +211,7 @@ export class SafelinkClient {
if (res.data.cursor) { if (res.data.cursor) {
redirectLogger.info( redirectLogger.info(
{cursor: res.data.cursor}, {cursor: res.data.cursor},
'received new cursor from Ozone', 'received new safelink events from Ozone',
) )
await this.setCursor(res.data.cursor) await this.setCursor(res.data.cursor)
} }
@@ -223,6 +224,7 @@ export class SafelinkClient {
// TODO: catch err // TODO: catch err
const res = await this.db.db const res = await this.db.db
.selectFrom('safelink_cursor') .selectFrom('safelink_cursor')
.selectAll()
.orderBy('createdAt desc') .orderBy('createdAt desc')
.limit(1) .limit(1)
.executeTakeFirst() .executeTakeFirst()
@@ -230,8 +232,6 @@ export class SafelinkClient {
if (!res) { if (!res) {
return '' return ''
} }
// @ts-ignore TODO: fix this
this.cursor = res.cursor this.cursor = res.cursor
} }
return this.cursor return this.cursor
@@ -281,6 +281,8 @@ export class OzoneAgent {
private session: CredentialSession private session: CredentialSession
private agent: AtpAgent private agent: AtpAgent
private refreshAt: number = 0
constructor(pdsHost: string, identifier: string, password: string) { constructor(pdsHost: string, identifier: string, password: string) {
this.identifier = identifier this.identifier = identifier
this.password = password this.password = password
@@ -289,13 +291,6 @@ export class OzoneAgent {
this.agent = new AtpAgent(this.session) this.agent = new AtpAgent(this.session)
} }
public async getSession(): Promise<CredentialSession> {
if (!this.session.hasSession) {
await this.getAgent()
}
return this.session
}
public async getAgent(): Promise<AtpAgent> { public async getAgent(): Promise<AtpAgent> {
if (!this.identifier && !this.password) { if (!this.identifier && !this.password) {
throw new Error( throw new Error(
@@ -310,6 +305,12 @@ export class OzoneAgent {
password: this.password, password: this.password,
}) })
redirectLogger.info('ozone session created successfully') redirectLogger.info('ozone session created successfully')
this.refreshAt = Date.now() + HOUR
}
if (Date.now() <= this.refreshAt) {
await this.session.refreshSession()
this.refreshAt = Date.now() + HOUR
} }
return this.agent return this.agent
+6 -4
View File
@@ -1,4 +1,4 @@
import {type Kysely} from 'kysely' import {type Kysely, sql} from 'kysely'
export async function up(db: Kysely<unknown>): Promise<void> { export async function up(db: Kysely<unknown>): Promise<void> {
await db.schema await db.schema
@@ -22,14 +22,16 @@ export async function up(db: Kysely<unknown>): Promise<void> {
.execute() .execute()
await db.schema await db.schema
.createIndex('safelink_rule_url_pattern_idx') .createIndex('safelink_rule_url_pattern_created_at_idx')
.on('safelink_rule') .on('safelink_rule')
.columns(['url', 'pattern']) .expression(sql`"url", "pattern", "createdAt" DESC`)
.execute() .execute()
} }
export async function down(db: Kysely<unknown>): Promise<void> { export async function down(db: Kysely<unknown>): Promise<void> {
await db.schema.dropIndex('safelink_rule_url_pattern_idx').execute() await db.schema
.dropIndex('safelink_rule_url_pattern_created_at_idx')
.execute()
await db.schema.dropTable('safelink_rule').execute() await db.schema.dropTable('safelink_rule').execute()
await db.schema.dropTable('safelink_cursor').execute() await db.schema.dropTable('safelink_cursor').execute()
} }