progress
ci / build (push) Failing after 9m2s Details

This commit is contained in:
CJ_Clippy 2024-08-02 17:29:02 -08:00
parent e82db2c250
commit 11af3dc87b
4 changed files with 41 additions and 30 deletions

View File

@ -16,7 +16,9 @@ interface Payload {
interface RecordingRecord { interface RecordingRecord {
id: number; id: number;
isAborted: boolean; recordingState: RecordingState;
fileSize: number;
discordMessageId: string;
} }
function assertPayload(payload: any): asserts payload is Payload { function assertPayload(payload: any): asserts payload is Payload {
@ -32,6 +34,7 @@ function assertEnv() {
if (!process.env.S3_ENDPOINT) throw new Error('S3_ENDPOINT was missing in env'); if (!process.env.S3_ENDPOINT) throw new Error('S3_ENDPOINT was missing in env');
if (!process.env.S3_BUCKET) throw new Error('S3_BUCKET was missing in env'); if (!process.env.S3_BUCKET) throw new Error('S3_BUCKET was missing in env');
if (!process.env.POSTGREST_URL) throw new Error('POSTGREST_URL was missing in env'); if (!process.env.POSTGREST_URL) throw new Error('POSTGREST_URL was missing in env');
if (!process.env.AUTOMATION_USER_JWT) throw new Error('AUTOMATION_USER_JWT was missing in env');
} }
async function getRecording(url: string, recordId: number, abortSignal: AbortSignal) { async function getRecording(url: string, recordId: number, abortSignal: AbortSignal) {
@ -48,37 +51,42 @@ async function getRecording(url: string, recordId: number, abortSignal: AbortSig
return record return record
} }
async function checkIfAborted(recordId: number): Promise<boolean> { // async function checkIfAborted(recordId: number): Promise<boolean> {
const res = await fetch(`${process.env.POSTGREST_URL}/records?id=eq.${recordId}`, { // const res = await fetch(`${process.env.POSTGREST_URL}/records?id=eq.${recordId}`, {
headers: { // headers: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json',
'Accepts': 'application/json' // 'Accepts': 'application/json'
} // }
}) // })
if (!res.ok) { // if (!res.ok) {
throw new Error(`failed to checkIfAborted. status=${res.status}, statusText=${res.statusText}`); // throw new Error(`failed to checkIfAborted. status=${res.status}, statusText=${res.statusText}`);
} // }
const body = await res.json() as RecordingRecord[]; // const body = await res.json() as RecordingRecord[];
if (!body[0]) throw new Error(`failed to get a record that matched recordId=${recordId}`) // if (!body[0]) throw new Error(`failed to get a record that matched recordId=${recordId}`)
return body[0].isAborted // return body[0].isAborted
} // }
async function updateDatabaseRecord({recordId, state, filesize}: { recordId: number, state: RecordingState, filesize: number }): Promise<void> { async function updateDatabaseRecord({recordId, recordingState, fileSize}: { recordId: number, recordingState?: RecordingState, fileSize: number }): Promise<RecordingRecord> {
const payload: any = {
file_size: fileSize
}
if (recordingState) payload.recording_state = recordingState;
const res = await fetch(`${process.env.POSTGREST_URL}/records?id=eq.${recordId}`, { const res = await fetch(`${process.env.POSTGREST_URL}/records?id=eq.${recordId}`, {
method: 'PATCH', method: 'PATCH',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accepts': 'application/json', 'Accepts': 'application/json',
'Prefer': 'return=representation' 'Prefer': 'return=representation',
'Authorization': `Bearer ${process.env.AUTOMATION_USER_JWT}`
}, },
body: JSON.stringify({ state, filesize }) body: JSON.stringify(payload)
}) })
if (!res.ok) { if (!res.ok) {
throw new Error(`failed to checkIfAborted. status=${res.status}, statusText=${res.statusText}`); throw new Error(`failed to updateDatabaseRecord. status=${res.status}, statusText=${res.statusText}`);
} }
const body = await res.json() as RecordingRecord[]; const body = await res.json() as RecordingRecord[];
if (!body[0]) throw new Error(`failed to get a record that matched recordId=${recordId}`) if (!body[0]) throw new Error(`failed to get a record that matched recordId=${recordId}`)
return body[0].isAborted return body[0]
} }
export const record: Task = async function (payload, helpers) { export const record: Task = async function (payload, helpers) {
@ -91,20 +99,21 @@ export const record: Task = async function (payload, helpers) {
try { try {
const record = await getRecording(url, recordId, abortController.signal) const record = await getRecording(url, recordId, abortController.signal)
// every 30s, we // every 30s, we
// 1. poll db to see if our job has been aborted by the user // 1. update the db record with the RecordingState and filesize
// 2. update the db record with the RecordingState and filesize // 2. poll db to see if our job has been aborted by the user
interval = setInterval(async () => { interval = setInterval(async () => {
try { try {
helpers.logger.info(`checkIfAborted()`) helpers.logger.info(`checkIfAborted()`)
const isAborted = await checkIfAborted(recordId) const updatePayload = { recordId, fileSize: record.counter }
if (isAborted) { const updatedRecord = await updateDatabaseRecord(updatePayload)
if (updatedRecord.recordingState === 'ended') {
helpers.logger.info(`record ${recordId} has been aborted by a user so we stop the recording now.`)
abortController.abort() abortController.abort()
} }
let state: RecordingState = 'recording'
} catch (e) { } catch (e) {
helpers.logger.error(`error while checking if this job was aborted. For sake of the recording in progress we are ignoring the following error. ${e}`) helpers.logger.error(`error while updating database. For sake of the recording in progress we are ignoring the following error. ${e}`)
} }
}, 30000) }, 3000)
// start recording and await the S3 upload being finished // start recording and await the S3 upload being finished
await record.start() await record.start()

View File

@ -29,7 +29,8 @@ async function createRecordingRecord(payload: Payload, helpers: Helpers): Promis
const record = { const record = {
url, url,
discord_message_id: discordMessageId, discord_message_id: discordMessageId,
is_aborted: false recording_state: 'pending',
file_size: 0
} }
const res = await fetch(`${process.env.POSTGREST_URL}/records`, { const res = await fetch(`${process.env.POSTGREST_URL}/records`, {
method: 'POST', method: 'POST',

View File

@ -4,7 +4,8 @@ CREATE TABLE api.records (
url TEXT NOT NULL, url TEXT NOT NULL,
discord_message_id TEXT NOT NULL, discord_message_id TEXT NOT NULL,
recording_state TEXT NOT NULL DEFAULT 'pending', recording_state TEXT NOT NULL DEFAULT 'pending',
file_size BIGINT NOT NULL DEFAULT 0 file_size BIGINT NOT NULL DEFAULT 0,
is_aborted BOOLEAN NOT NULL DEFAULT FALSE
); );
-- roles & permissions for our backend automation user -- roles & permissions for our backend automation user

View File

@ -1,7 +1,7 @@
{ {
"name": "@futureporn/migrations", "name": "@futureporn/migrations",
"type": "module", "type": "module",
"version": "0.4.1", "version": "0.5.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {