mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-26 02:58:48 -06:00
* feat: privacy, imprint, and terms URL env vars now do not need rebuilding * feat: disable_singup env var now do not need rebuilding * feat: password_reset_disabled env var now do not need rebuilding * feat: email_verification_disabled env var now do not need rebuilding * feat: github_oauth & google_oauth env var now do not need rebuilding * feat: move logic of env vars to serverside and send boolean client-side * feat: invite_disabled env var now do not need rebuilding * feat: rename vars logically * feat: migration guide * feat: update docker-compose as per v1.1 * deprecate: unused NEXT_PUBLIC_VERCEL_URL & VERCEL_URL * deprecate: unused RAILWAY_STATIC_URL * deprecate: unused RENDER_EXTERNAL_URL * deprecate: unused HEROKU_APP_NAME * fix: define WEBAPP_URL & replace NEXT_WEBAPP_URL with it * migrate: NEXT_PUBLIC_IS_FORMBRICKS_CLOUD to IS_FORMBRICKS_CLOUD * chore: move all env parsing to a constants.ts from page files * feat: migrate client side envs to server side * redo: isFormbricksCloud to navbar serverside page * fix: constants is now a server only file * fix: removal of use swr underway * fix: move 1 tag away from swr to service * feat: move away from tags swr * feat: move away from surveys swr * feat: move away from eventClass swr * feat: move away from event swr * fix: make constants server-only * remove comments from .env.example, use constants in MetaInformation * clean up services * rename tag function * fix build error * fix smaller bugs, fix Response % not working in summary --------- Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
98 lines
3.1 KiB
TypeScript
98 lines
3.1 KiB
TypeScript
import { TResponseUpdate } from "@formbricks/types/v1/responses";
|
|
import { createResponse, updateResponse } from "./client/response";
|
|
import SurveyState from "./surveyState";
|
|
import { markDisplayResponded } from "./client/display";
|
|
|
|
interface QueueConfig {
|
|
apiHost: string;
|
|
retryAttempts: number;
|
|
onResponseSendingFailed?: (responseUpdate: TResponseUpdate) => void;
|
|
setSurveyState?: (state: SurveyState) => void;
|
|
personId?: string;
|
|
}
|
|
|
|
export class ResponseQueue {
|
|
private queue: TResponseUpdate[] = [];
|
|
private config: QueueConfig;
|
|
private surveyState: SurveyState;
|
|
private isRequestInProgress = false;
|
|
|
|
constructor(config: QueueConfig, surveyState: SurveyState) {
|
|
this.config = config;
|
|
this.surveyState = surveyState;
|
|
}
|
|
|
|
add(responseUpdate: TResponseUpdate) {
|
|
// update survey state
|
|
this.surveyState.accumulateResponse(responseUpdate);
|
|
if (this.config.setSurveyState) {
|
|
this.config.setSurveyState(this.surveyState);
|
|
}
|
|
// add response to queue
|
|
this.queue.push(responseUpdate);
|
|
this.processQueue();
|
|
}
|
|
|
|
async processQueue() {
|
|
if (this.isRequestInProgress) return;
|
|
if (this.queue.length === 0) return;
|
|
|
|
this.isRequestInProgress = true;
|
|
|
|
const responseUpdate = this.queue[0];
|
|
let attempts = 0;
|
|
|
|
while (attempts < this.config.retryAttempts) {
|
|
const success = await this.sendResponse(responseUpdate);
|
|
if (success) {
|
|
this.queue.shift(); // remove the successfully sent response from the queue
|
|
break; // exit the retry loop
|
|
}
|
|
console.error("Formbricks: Failed to send response. Retrying...", attempts);
|
|
attempts++;
|
|
}
|
|
|
|
if (attempts >= this.config.retryAttempts) {
|
|
// Inform the user after 2 failed attempts
|
|
console.error("Failed to send response after 2 attempts.");
|
|
// If the response is finished and thus fails finally, inform the user
|
|
if (this.surveyState.responseAcc.finished && this.config.onResponseSendingFailed) {
|
|
this.config.onResponseSendingFailed(this.surveyState.responseAcc);
|
|
}
|
|
this.queue.shift(); // remove the failed response from the queue
|
|
}
|
|
|
|
this.isRequestInProgress = false;
|
|
this.processQueue(); // process the next item in the queue if any
|
|
}
|
|
|
|
async sendResponse(responseUpdate: TResponseUpdate): Promise<boolean> {
|
|
try {
|
|
if (this.surveyState.responseId !== null) {
|
|
await updateResponse(responseUpdate, this.surveyState.responseId, this.config.apiHost);
|
|
} else {
|
|
const response = await createResponse(
|
|
{ ...responseUpdate, surveyId: this.surveyState.surveyId, personId: this.config.personId || null },
|
|
this.config.apiHost
|
|
);
|
|
if (this.surveyState.displayId) {
|
|
markDisplayResponded(this.surveyState.displayId, this.config.apiHost);
|
|
}
|
|
this.surveyState.updateResponseId(response.id);
|
|
if (this.config.setSurveyState) {
|
|
this.config.setSurveyState(this.surveyState);
|
|
}
|
|
}
|
|
return true;
|
|
} catch (error) {
|
|
console.error(error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// update surveyState
|
|
updateSurveyState(surveyState: SurveyState) {
|
|
this.surveyState = surveyState;
|
|
}
|
|
}
|