added sse2

This commit is contained in:
2026-06-18 20:04:50 +03:30
parent f3aaf9d7c0
commit e27fdeb102
4 changed files with 62 additions and 29 deletions
+39 -12
View File
@@ -2,14 +2,16 @@ import type { Price } from '@/models/home'
import type { Product } from '@/models/products'
import { Modal } from 'ant-design-vue'
import { getConfigApp } from '@/utils/config'
import { priceSocketConnected, priceWssEnabled } from '@/utils/priceSocketState'
import { priceSocketConnected, priceStreamLifecycle, priceWssEnabled } from '@/utils/priceSocketState'
export { priceSocketConnected, priceWssEnabled, shouldUsePricePolling } from '@/utils/priceSocketState'
export { priceSocketConnected, priceStreamLifecycle, priceWssEnabled, shouldUsePricePolling } from '@/utils/priceSocketState'
const RECONNECT_BASE_MS = 3000
const RECONNECT_MAX_MS = 30000
const FAILURES_BEFORE_ALERT = 4
const STALE_STREAM_MS = 45000
/** بدون event قیمت؛ ping هر ۵ث از سرور activity را تازه می‌کند */
const STALE_STREAM_MS = 120000
const FALLBACK_POLL_DELAY_MS = 2500
let eventSource: EventSource | null = null
let subscribers = 0
@@ -21,6 +23,7 @@ let reconnectAttempt = 0
let lastStreamEventAt = 0
let networkAlertOpen = false
let listenersBound = false
let fallbackPollTimer: ReturnType<typeof setTimeout> | undefined
function isTruthySetting(value: unknown, defaultValue = true): boolean {
if (value === null || value === undefined || value === '') {
@@ -95,6 +98,23 @@ function startStaleCheck() {
}, 15000)
}
function clearFallbackPollTimer() {
if (fallbackPollTimer) {
clearTimeout(fallbackPollTimer)
fallbackPollTimer = undefined
}
}
function scheduleFallbackPoll() {
clearFallbackPollTimer()
fallbackPollTimer = setTimeout(() => {
fallbackPollTimer = undefined
if (!stopped && subscribers > 0 && !priceSocketConnected.value) {
void runFallbackPoll()
}
}, FALLBACK_POLL_DELAY_MS)
}
async function runFallbackPoll() {
if (!priceWssEnabled.value || priceSocketConnected.value) {
return
@@ -211,6 +231,10 @@ function bindStreamEvents(source: EventSource) {
}
})
source.addEventListener('ping', () => {
touchStreamActivity()
})
source.onmessage = () => {
touchStreamActivity()
}
@@ -220,9 +244,10 @@ function handleStreamLost(scheduleRetry = true) {
const wasConnected = priceSocketConnected.value
disconnectSourceOnly()
priceSocketConnected.value = false
priceStreamLifecycle.value = scheduleRetry ? 'connecting' : 'closed'
if (wasConnected || scheduleRetry) {
void runFallbackPoll()
if ((wasConnected || scheduleRetry) && scheduleRetry) {
scheduleFallbackPoll()
}
if (scheduleRetry && !stopped && subscribers > 0) {
@@ -233,6 +258,7 @@ function handleStreamLost(scheduleRetry = true) {
function disconnectSourceOnly() {
stopStaleCheck()
clearFallbackPollTimer()
if (eventSource) {
eventSource.onopen = null
eventSource.onerror = null
@@ -250,6 +276,7 @@ function connect() {
const url = resolveStreamUrl()
if (!url) {
priceSocketConnected.value = false
priceStreamLifecycle.value = 'closed'
return
}
@@ -261,6 +288,8 @@ function connect() {
disconnectSourceOnly()
}
priceStreamLifecycle.value = 'connecting'
try {
eventSource = new EventSource(url)
} catch (error) {
@@ -274,7 +303,9 @@ function connect() {
eventSource.onopen = () => {
reconnectAttempt = 0
clearReconnectTimer()
clearFallbackPollTimer()
networkAlertOpen = false
priceStreamLifecycle.value = 'open'
priceSocketConnected.value = true
touchStreamActivity()
startStaleCheck()
@@ -282,13 +313,7 @@ function connect() {
eventSource.onerror = () => {
const state = eventSource?.readyState
if (state === EventSource.OPEN) {
return
}
if (state === EventSource.CONNECTING) {
priceSocketConnected.value = false
void runFallbackPoll()
if (state === EventSource.OPEN || state === EventSource.CONNECTING) {
return
}
@@ -298,8 +323,10 @@ function connect() {
function disconnect() {
clearReconnectTimer()
clearFallbackPollTimer()
disconnectSourceOnly()
priceSocketConnected.value = false
priceStreamLifecycle.value = 'idle'
}
export function forceReconnect() {