{"version":3,"file":"index-B-QRKUJo.js","sources":["../../../app/assets/javascripts/app/network_latency_to_spacious_app_server/index.ts"],"sourcesContent":["\nimport log from \"plugins/loglevel/index\"\n\nimport retry from \"retry\"\nimport Promise from \"plugins/bluebird/index\"\nimport WindowState from \"app/window_state/index\"\nimport DataRetriever from \"app/data_retriever\"\nimport {\n captureMessage,\n} from \"app/error_reporting\"\n\n/* eslint-disable no-unused-vars */\nenum NetworkLatencyStatuses {\n LATENCY_UNKNOWN = \"LATENCY_UNKNOWN\",\n LATENCY_DETECTED = \"LATENCY_DETECTED\",\n}\n/* eslint-enable no-unused-vars */\n\ninterface NetworkLatencyToSpaciousResult {\n latency_value_in_ms: number,\n status: NetworkLatencyStatuses,\n}\n\n// Represents unknown\n// 1 day in ms\nconst UNKNOWN_NETWORK_LATENCY_TO_SERVER_MS_VALUE = 86400 * 1000\nlet network_latency_to_server_ms = UNKNOWN_NETWORK_LATENCY_TO_SERVER_MS_VALUE\nlet status = NetworkLatencyStatuses.LATENCY_UNKNOWN\n\n\nconst ENDPOINT_IDENTIFIER = \"network_latency_to_spacious_app_server\"\n\n\nconst refreshNetworkLatencyPromise = (): Promise => {\n // Set fallback value, although `beforeSend` should set it anyway\n let start_time = new Date().getTime()\n\n const timeout_options = {\n minTimeout: 10 * 1000,\n maxTimeout: 60 * 1000,\n factor: 2,\n // Should become 10,20,40,60\n retries: 4,\n }\n\n // We are not waiting locally, only having different timeout values on AJAX\n const retry_operation = retry.operation({\n retries: 5,\n factor: 1,\n minTimeout: 0,\n maxTimeout: 0,\n randomize: false,\n })\n\n const url = \"/ping_app\"\n const fetch_options: RequestInit = {\n method: \"GET\",\n // Shouldn't allow redirect by default due to potential bug\n // Allow later if really needed\n redirect: \"error\" as \"error\",\n // Safer default, update to other value is required\n referrerPolicy: \"same-origin\" as \"same-origin\",\n // Safer default, update to other value is required\n credentials: \"same-origin\" as \"same-origin\",\n // Just explicitly stating the default\n cache: \"default\" as \"default\",\n headers: {\n // AJAX simulation\n \"X-Requested-With\": \"XMLHttpRequest\",\n },\n }\n\n return new Promise((resolve) => {\n // currentAttempt is 1-based, tested manually\n retry_operation.attempt((currentAttempt) => {\n // `attempt` is zero-indexed in `createTimeout` but `currentAttempt` is 1 based\n const current_timeout_ms = retry.createTimeout(currentAttempt - 1, timeout_options)\n\n // region timeout\n const abort_controller = new AbortController()\n fetch_options.signal = abort_controller.signal\n\n // https://stackoverflow.com/a/50101022/838346\n const timeoutId = setTimeout(() => {\n abort_controller.abort()\n }, current_timeout_ms)\n // endregion timeout\n\n start_time = new Date().getTime()\n window.fetch(\n url,\n fetch_options,\n )\n .then((response) => {\n clearTimeout(timeoutId)\n if (response.ok) {\n const new_network_latency_to_server_ms = new Date().getTime() - start_time\n status = NetworkLatencyStatuses.LATENCY_DETECTED\n // If unknown, assign detected value anyway\n //\n // If new value < existing value, assign new value too\n // since values fetched during script load / dom load\n // might be inaccurate due to busy main thread\n if (network_latency_to_server_ms === UNKNOWN_NETWORK_LATENCY_TO_SERVER_MS_VALUE ||\n new_network_latency_to_server_ms < network_latency_to_server_ms) {\n\n network_latency_to_server_ms = new_network_latency_to_server_ms\n }\n\n log.info(`Network Latency to Spacious App Server: ${network_latency_to_server_ms}ms`)\n\n resolve()\n return\n }\n\n const context = {\n fetch_options: JSON.stringify(fetch_options),\n http_status_code: response.status,\n endpoint_identifier: ENDPOINT_IDENTIFIER,\n current_attempt: currentAttempt,\n }\n\n // No error should be reported for AJAX errors\n // caused by page being unloaded\n if (WindowState.isUnloaded()) {\n resolve()\n return\n }\n\n // Could be gateway server not ready\n if (response.status === 400 || response.status === 404 || response.status === 503) {\n resolve()\n return\n }\n\n if (retry_operation.retry(new Error(response.statusText))) {\n return\n }\n\n // Status Code 0 Could be caused by:\n // - Illegal CORS (We don't use it anyway)\n // - Firewall blocking/filtering (We can't fix)\n // - Request is cancelled (not `abort()`) (Expected)\n // - Browser extension (any Adblocker) (We can't fix)\n //\n // https://stackoverflow.com/a/14507670/838346\n //\n // So we don't report status code 0\n //\n // Some clients got strange response codes\n if (response.status !== 0 && isSaneUserAgent() && isSaneLocation()) {\n captureMessage(\n `Error occurred when using ajax with status <${(response.status || \"unknown\")}> on endpoint <${ENDPOINT_IDENTIFIER}>`,\n context,\n )\n }\n\n // Resolve with status stayed in unknown\n resolve()\n })\n .catch((error) => {\n if (retry_operation.retry(error)) {\n return\n }\n\n // Resolve with status stayed in unknown\n resolve()\n })\n })\n })\n}\n\nfunction getNetworkLatencyToSpaciousAppServerPromise(): Promise {\n return refreshNetworkLatencyPromise()\n .then(() => {\n return {\n latency_value_in_ms: network_latency_to_server_ms,\n status: status,\n }\n })\n}\n\n// Not reporting errors from \"insane\" user agents\nfunction isSaneUserAgent(): boolean {\n return [\n /Baiduspider-render/i,\n /YandexBot/i,\n ].every((regex) => !regex.test(window.navigator.userAgent))\n}\n\n// Not reporting errors from \"insane\" locations\nfunction isSaneLocation(): boolean {\n return !DataRetriever.get(\"current-location-country-code-is-china\")\n}\n\n// Don't run on script load or get inaccurate result due to busy main thread\n// refreshNetworkLatencyPromise()\n\n\nexport {\n getNetworkLatencyToSpaciousAppServerPromise,\n refreshNetworkLatencyPromise as refreshNetworkLatencyToSpaciousAppServerPromise,\n NetworkLatencyStatuses as NetworkLatencyToSpaciousAppServerStatues,\n}\n"],"names":["NetworkLatencyStatuses","UNKNOWN_NETWORK_LATENCY_TO_SERVER_MS_VALUE","network_latency_to_server_ms","status","ENDPOINT_IDENTIFIER","refreshNetworkLatencyPromise","start_time","timeout_options","retry_operation","retry","url","fetch_options","Promise","resolve","currentAttempt","current_timeout_ms","abort_controller","timeoutId","response","new_network_latency_to_server_ms","log","context","WindowState","isSaneUserAgent","isSaneLocation","captureMessage","error","getNetworkLatencyToSpaciousAppServerPromise","regex","DataRetriever"],"mappings":"2MAYK,IAAAA,GAAAA,IACHA,EAAA,gBAAoB,kBACpBA,EAAA,iBAAoB,mBAFjBA,IAAAA,GAAA,CAAA,CAAA,EAaL,MAAMC,EAA6C,MAAQ,IAC3D,IAAIC,EAA+BD,EAC/BE,EAAS,kBAGb,MAAMC,EAAsB,yCAGtBC,EAA+B,IAAqB,CAExD,IAAIC,EAAa,IAAI,KAAK,EAAE,QAAQ,EAEpC,MAAMC,EAAkB,CACtB,WAAY,GAAK,IACjB,WAAY,GAAK,IACjB,OAAY,EAEZ,QAAY,CACd,EAGMC,EAAkBC,EAAM,UAAU,CACtC,QAAY,EACZ,OAAY,EACZ,WAAY,EACZ,WAAY,EACZ,UAAY,EAAA,CACb,EAEKC,EAAM,YACNC,EAA6B,CACjC,OAAgB,MAGhB,SAAgB,QAEhB,eAAgB,cAEhB,YAAgB,cAEhB,MAAgB,UAChB,QAAgB,CAEd,mBAAoB,gBAAA,CAExB,EAEO,OAAA,IAAIC,EAASC,GAAY,CAEdL,EAAA,QAASM,GAAmB,CAE1C,MAAMC,EAAqBN,EAAM,cAAcK,EAAiB,EAAGP,CAAe,EAG5ES,EAAmB,IAAI,gBAC7BL,EAAc,OAASK,EAAiB,OAGlC,MAAAC,EAAY,WAAW,IAAM,CACjCD,EAAiB,MAAM,GACtBD,CAAkB,EAGRT,EAAA,IAAI,KAAK,EAAE,QAAQ,EACzB,OAAA,MACLI,EACAC,CAAA,EAED,KAAMO,GAAa,CAElB,GADA,aAAaD,CAAS,EAClBC,EAAS,GAAI,CACf,MAAMC,EAAmC,IAAI,KAAK,EAAE,QAAY,EAAAb,EACvDH,EAAA,oBAMLD,IAAiCD,GACnCkB,EAAmCjB,KAEJA,EAAAiB,GAG7BC,EAAA,KAAK,2CAA2C,OAAAlB,EAA4B,KAAI,EAE5EW,EAAA,EACR,MAAA,CAGF,MAAMQ,EAAU,CACd,cAAsB,KAAK,UAAUV,CAAa,EAClD,iBAAsBO,EAAS,OAC/B,oBAAsBd,EACtB,gBAAsBU,CACxB,EAII,GAAAQ,EAAY,aAAc,CACpBT,EAAA,EACR,MAAA,CAIE,GAAAK,EAAS,SAAW,KAAOA,EAAS,SAAW,KAAOA,EAAS,SAAW,IAAK,CACzEL,EAAA,EACR,MAAA,CAGEL,EAAgB,MAAM,IAAI,MAAMU,EAAS,UAAU,CAAC,IAepDA,EAAS,SAAW,GAAKK,EAAgB,GAAKC,KAChDC,EACE,+CAAgD,OAAAP,EAAS,QAAU,UAAU,mBAAkB,OAAAd,EAAmB,KAClHiB,CACF,EAIMR,EAAA,EAAA,CACT,EACA,MAAOa,GAAU,CACZlB,EAAgB,MAAMkB,CAAK,GAKvBb,EAAA,CAAA,CACT,CAAA,CACF,CAAA,CACF,CACH,EAEA,SAASc,GAAuF,CACvF,OAAAtB,EAAA,EACN,KAAK,KACG,CACL,oBAAsBH,EACtB,OAAAC,CACF,EACD,CACH,CAGA,SAASoB,GAA2B,CAC3B,MAAA,CACL,sBACA,YAAA,EACA,MAAOK,GAAU,CAACA,EAAM,KAAK,OAAO,UAAU,SAAS,CAAC,CAC5D,CAGA,SAASJ,GAA0B,CAC1B,MAAA,CAACK,EAAc,IAAI,wCAAwC,CACpE"}