Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
cb33214
feat(websocket): Phase 1 — replace SSE notification count with WebSocket
mohammad-rj Mar 23, 2026
6073438
chore: add github.com/coder/websocket dependency to go.mod
mohammad-rj Mar 23, 2026
3076f90
fix(websocket): use gitea modules/json, write raw bytes directly
mohammad-rj Mar 23, 2026
096bdd0
fix(websocket): avoid data race with timeutil.MockUnset in tests
mohammad-rj Mar 23, 2026
6aba649
chore: run make tidy to add coder/websocket to go-licenses.json
mohammad-rj Mar 24, 2026
89e5084
fix(websocket): address silverwind review feedback
mohammad-rj Mar 24, 2026
1537d8f
fix(websocket): auth via IsSigned check instead of reqSignIn middleware
mohammad-rj Mar 24, 2026
f2450cc
fix(websocket): remove export{} from sharedworker entry point, rename…
mohammad-rj Mar 24, 2026
c1ba182
fix(websocket): declare sharedworker as ES module and fix port cleanup
mohammad-rj Mar 24, 2026
b9a94c6
feat(websocket): Phase 1 — replace SSE notification count with WebSocket
mohammad-rj Mar 23, 2026
69324f3
chore: add github.com/coder/websocket dependency to go.mod
mohammad-rj Mar 23, 2026
f26aa2f
fix(websocket): use gitea modules/json, write raw bytes directly
mohammad-rj Mar 23, 2026
634b638
fix(websocket): avoid data race with timeutil.MockUnset in tests
mohammad-rj Mar 23, 2026
d526aa6
chore: run make tidy to add coder/websocket to go-licenses.json
mohammad-rj Mar 24, 2026
1a576b1
fix(websocket): address silverwind review feedback
mohammad-rj Mar 24, 2026
b47686c
fix(websocket): auth via IsSigned check instead of reqSignIn middleware
mohammad-rj Mar 24, 2026
bf564d3
fix(websocket): remove export{} from sharedworker entry point, rename…
mohammad-rj Mar 24, 2026
7e8f5a8
fix(websocket): declare sharedworker as ES module and fix port cleanup
mohammad-rj Mar 24, 2026
2a902d1
fix(websocket): add WsSource to eventsource.sharedworker, remove webs…
mohammad-rj Mar 30, 2026
48ec6f2
ci: add compliance workflow
mohammad-rj Mar 30, 2026
ed3bd91
ci: expand compliance workflow to match GitHub pull-compliance.yml (1…
mohammad-rj Mar 30, 2026
af2fadb
ci: add cleanup steps after each job to free disk space
mohammad-rj Mar 30, 2026
3ec0ed9
ci: trigger run with capacity=5 parallel workers
mohammad-rj Mar 30, 2026
155ef8f
ci: trigger run after disk cleanup
mohammad-rj Mar 30, 2026
42f5342
Merge upstream/main to bring branch up to date with Vite migration an…
mohammad-rj Mar 30, 2026
36b28c7
fix(websocket): add WsSource to eventsource.sharedworker, remove webs…
mohammad-rj Mar 30, 2026
256aeb9
feat(websocket): Phase 2 — migrate stopwatches/logout to WebSocket, r…
mohammad-rj Apr 1, 2026
bf7c30e
fix(websocket): replace json.RawMessage with any in stopwatchesEvent
mohammad-rj Apr 1, 2026
9cf7ea8
fix(stopwatch): show icon dynamically in tabs loaded before stopwatch…
mohammad-rj Apr 1, 2026
0dc3607
fix(stopwatch): publish empty-stopwatches push on stop, not only cancel
mohammad-rj Apr 2, 2026
075af8e
fix(stopwatch): prevent page reload when stopping/cancelling from nav…
mohammad-rj Apr 2, 2026
111ca0c
fix(stopwatch): prevent page reload when starting/stopping from issue…
mohammad-rj Apr 2, 2026
10f8e1e
chore(stopwatch): remove dead no-event-source code paths
mohammad-rj Apr 2, 2026
99ad25b
chore: remove local CI workflow (not for upstream)
mohammad-rj Apr 2, 2026
fdc94c3
Merge remote-tracking branch 'origin/feat/websocket-migration' into c…
mohammad-rj Apr 2, 2026
0af095a
Merge remote-tracking branch 'upstream/main' into ci-phase2-push
mohammad-rj Apr 2, 2026
cb41638
refactor(websocket): unify Init, add notification hook, accept anonym…
mohammad-rj Apr 3, 2026
abe5c17
refactor(websocket): extract notification and stopwatch publish helpers
mohammad-rj Apr 3, 2026
f54d567
fix(stopwatch): register sidebar handlers before navbar early return
mohammad-rj Apr 3, 2026
98ad58f
Merge remote-tracking branch 'upstream/main' into final-for-github
mohammad-rj Apr 3, 2026
ec54754
Merge remote-tracking branch 'origin/main' into feat/websocket-migration
silverwind Apr 24, 2026
0626009
websocket: add server-side ping keepalive and pubsub broker tests
silverwind Apr 24, 2026
7004250
refactor: clean up residual EventSource/SSE references
silverwind Apr 24, 2026
5e6e385
websocket: address open review feedback
silverwind Apr 24, 2026
0627122
websocket: address remaining review follow-ups
silverwind Apr 24, 2026
f6e894a
websocket: tighten event wire contract
silverwind Apr 24, 2026
a308c74
websocket: narrow scope to the SSE→WebSocket migration
silverwind Apr 24, 2026
ce24ef7
websocket: tear down cleanly on shutdown, drop empty broker topics
silverwind Apr 24, 2026
e483e4c
websocket: make the pipeline push-only, drop all polling
silverwind Apr 24, 2026
696e792
Merge remote-tracking branch 'origin/main' into pr-36965-ci
silverwind Apr 24, 2026
eb8d79b
fix(stopwatch): only set form-fetch-action class when a stopwatch is …
silverwind Apr 24, 2026
509ce95
websocket: fold publish helper, share TS event-name constants
silverwind Apr 24, 2026
4cd8010
websocket: correct the sharedworker duplicate-constants comment
silverwind Apr 24, 2026
c730de1
websocket: share event-name constants via module SharedWorker
silverwind Apr 24, 2026
eb3be05
websocket: fix ping deadlock and worker reconnect leak
silverwind Apr 24, 2026
e83f616
websocket: clean up comments, simplify event path, add e2e coverage
silverwind Apr 24, 2026
31a5342
websocket: drop ping-cycle e2e test and its env override
silverwind Apr 24, 2026
159df9e
Replace USER_EVENT_* string constants with TypeScript union types
silverwind Apr 24, 2026
51bdf3f
manifest_test: fix wrong path for user-events.sharedworker entry
silverwind Apr 24, 2026
25a2b0f
e2e: drop __userEventsWsReady, use retry/timeout for connect race
silverwind Apr 24, 2026
00957e0
move user-events types into shared types.ts
silverwind Apr 24, 2026
c2a2778
simplify type sync comment
silverwind Apr 24, 2026
84fe4ae
silence playwright/no-wait-for-timeout in events tests
silverwind Apr 26, 2026
c6f5df2
share single SharedWorker between notification and stopwatch
silverwind Apr 26, 2026
6e2e733
refactor user-events worker into typed pub/sub singleton
silverwind Apr 26, 2026
f6c83fd
simplify: drop dead status path, trim narrating comments
silverwind Apr 26, 2026
295177e
Merge branch 'main' into feat/websocket-migration
silverwind Apr 26, 2026
37d6a7c
type user-events as a discriminated union, drop JSON round-trip
silverwind Apr 26, 2026
368a080
ws: jitter reconnect, stop on auth-required close
silverwind Apr 26, 2026
713b885
ws: use IANA close code 3000 (Unauthorized) instead of custom 4401
silverwind Apr 26, 2026
3bc2c9d
Merge branch 'main' into feat/websocket-migration
wxiaoguang Apr 26, 2026
2133553
Update routers/web/websocket/websocket.go
wxiaoguang Apr 26, 2026
88740eb
tests/e2e: cover sidebar Start timer button click path
silverwind Apr 26, 2026
022a805
fix(stopwatch): JSONOK instead of JSONRedirect("") for sidebar actions
silverwind Apr 26, 2026
aa0aff1
websocket: drop unused routing import
silverwind Apr 26, 2026
23e1406
Merge remote-tracking branch 'origin/main' into feat/websocket-migration
silverwind May 8, 2026
6284286
tests: update TestRequireSignInView to use /-/ws
silverwind May 8, 2026
102db5e
ws: write timeout + clarify close code 3000 comment
silverwind May 8, 2026
76bfed9
drop unused noscript href on active-stopwatch icon
silverwind May 8, 2026
8bab18a
stopwatch: revert JSONOK back to JSONRedirect("")
silverwind May 8, 2026
56ecb7d
Merge remote-tracking branch 'origin/main' into feat/websocket-migration
silverwind May 8, 2026
864370c
ws: drop redundant logoutPrefix byte-prefix scan
silverwind May 8, 2026
b162b44
pubsub: make Subscribe cancel idempotent
silverwind May 8, 2026
cee3dc4
minor cleanups
silverwind May 8, 2026
c648306
tests/e2e: parallelize loginUser with API setup in stopwatch tests
silverwind May 8, 2026
08493cf
refactor(notifications): lift NotificationCountChange into service wr…
silverwind May 18, 2026
e7ecf16
refactor(pubsub): extract Broker interface, rename impl to MemoryBroker
silverwind May 18, 2026
f489ad7
feat(pubsub): add Redis backend for cross-process event fan-out
silverwind May 18, 2026
f927198
simplify: pubsub redis concurrency, wrapper API consistency
silverwind May 18, 2026
2a49b99
test(pubsub): swap real redis-server for miniredis, add cross-broker …
silverwind May 18, 2026
508b180
review fixes: redis subscribe lock window, ping context, worker unsub…
silverwind May 18, 2026
6826c42
Merge branch 'main' into feat/websocket-migration
silverwind May 18, 2026
f0a8bb0
fix(pubsub): wait for SUBSCRIBE ack before returning from Subscribe
silverwind May 18, 2026
7f36592
simplify pass: pubsub retry, dispatch dedup, rewriteLogout fast path
silverwind May 18, 2026
a910a1d
Merge branch 'main' into feat/websocket-migration
lunny May 20, 2026
89dd1b8
Merge remote-tracking branch 'upstream/main' into feat/websocket-migr…
Jul 3, 2026
8b0dee2
fix: remove leftover SSE-era imports and template literal after mergi…
Jul 3, 2026
47671b8
refactor(websocket): scope pubsub settings under [websocket] section
Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions assets/go-licenses.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ require (
github.com/caddyserver/certmagic v0.25.1
github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20251013092601-6327009efd21
github.com/chi-middleware/proxy v1.1.1
github.com/coder/websocket v1.8.14
Comment thread
mohammad-rj marked this conversation as resolved.
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
github.com/dlclark/regexp2 v1.11.5
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8=
github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g=
github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
Expand Down
2 changes: 2 additions & 0 deletions routers/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"code.gitea.io/gitea/services/task"
"code.gitea.io/gitea/services/uinotification"
"code.gitea.io/gitea/services/webhook"
websocket_service "code.gitea.io/gitea/services/websocket"
)

func mustInit(fn func() error) {
Expand Down Expand Up @@ -160,6 +161,7 @@ func InitWebInstalled(ctx context.Context) {
mustInit(task.Init)
mustInit(repo_migrations.Init)
eventsource.GetManager().Init()
mustInit(websocket_service.Init)
mustInitCtx(ctx, mailer_incoming.Init)

mustInitCtx(ctx, syncAppConfForGit)
Expand Down
2 changes: 2 additions & 0 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"code.gitea.io/gitea/routers/web/user"
user_setting "code.gitea.io/gitea/routers/web/user/setting"
"code.gitea.io/gitea/routers/web/user/setting/security"
gitea_websocket "code.gitea.io/gitea/routers/web/websocket"
auth_service "code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
Expand Down Expand Up @@ -588,6 +589,7 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) {
}, reqSignOut)

Comment thread
silverwind marked this conversation as resolved.
m.Any("/user/events", routing.MarkLongPolling, events.Events)
m.Get("/-/ws", gitea_websocket.Serve)
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated

m.Group("/login/oauth", func() {
m.Group("", func() {
Expand Down
51 changes: 51 additions & 0 deletions routers/web/websocket/websocket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
// SPDX-License-Identifier: MIT

package websocket

import (
"fmt"

"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/pubsub"

gitea_ws "github.com/coder/websocket"
)

// Serve handles WebSocket upgrade and event delivery for the signed-in user.
func Serve(ctx *context.Context) {
if !ctx.IsSigned {
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
ctx.Status(401)
return
}

conn, err := gitea_ws.Accept(ctx.Resp, ctx.Req, &gitea_ws.AcceptOptions{
InsecureSkipVerify: false,
})
if err != nil {
log.Error("websocket: accept failed: %v", err)
return
}
defer conn.CloseNow() //nolint:errcheck // CloseNow is best-effort; error is intentionally ignored

topic := fmt.Sprintf("user-%d", ctx.Doer.ID)
ch, cancel := pubsub.DefaultBroker.Subscribe(topic)
defer cancel()
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated

wsCtx := ctx.Req.Context()
for {
select {
case <-wsCtx.Done():
return
case msg, ok := <-ch:
if !ok {
return
}
if err := conn.Write(wsCtx, gitea_ws.MessageText, msg); err != nil {
log.Trace("websocket: write failed: %v", err)
return
}
Comment thread
silverwind marked this conversation as resolved.
}
}
}
11 changes: 11 additions & 0 deletions services/context/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
package context

import (
"bufio"
"net"
"net/http"

web_types "code.gitea.io/gitea/modules/web/types"
Expand Down Expand Up @@ -67,6 +69,15 @@ func (r *Response) WriteHeader(statusCode int) {
}
}

// Hijack implements http.Hijacker by forwarding to the underlying ResponseWriter.
// This is required for WebSocket upgrades.
func (r *Response) Hijack() (net.Conn, *bufio.ReadWriter, error) {
if h, ok := r.ResponseWriter.(http.Hijacker); ok {
return h.Hijack()
}
return nil, nil, http.ErrNotSupported
}

// Flush flushes cached data
func (r *Response) Flush() {
if f, ok := r.ResponseWriter.(http.Flusher); ok {
Expand Down
65 changes: 65 additions & 0 deletions services/pubsub/broker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
// SPDX-License-Identifier: MIT

package pubsub

import (
"sync"
)

// Broker is a simple in-memory pub/sub broker.
// It supports fan-out: one Publish call delivers the message to all active subscribers.
type Broker struct {
mu sync.RWMutex
subs map[string][]chan []byte
}

// DefaultBroker is the global singleton used by both routers and notifiers.
var DefaultBroker = NewBroker()

// NewBroker creates a new in-memory Broker.
func NewBroker() *Broker {
return &Broker{
subs: make(map[string][]chan []byte),
}
}

// Subscribe returns a channel that receives messages published to topic.
// Call the returned cancel function to unsubscribe.
func (b *Broker) Subscribe(topic string) (<-chan []byte, func()) {
ch := make(chan []byte, 8)

b.mu.Lock()
b.subs[topic] = append(b.subs[topic], ch)
b.mu.Unlock()

cancel := func() {
b.mu.Lock()
defer b.mu.Unlock()
subs := b.subs[topic]
for i, sub := range subs {
if sub == ch {
b.subs[topic] = append(subs[:i], subs[i+1:]...)
break
}
}
close(ch)
}
return ch, cancel
}

// Publish sends msg to all subscribers of topic.
// Non-blocking: slow subscribers are skipped.
func (b *Broker) Publish(topic string, msg []byte) {
b.mu.RLock()
subs := b.subs[topic]
b.mu.RUnlock()

for _, ch := range subs {
select {
case ch <- msg:
default:
// subscriber too slow — skip
}
}
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
}
82 changes: 82 additions & 0 deletions services/websocket/notifier.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
// SPDX-License-Identifier: MIT

package websocket

import (
"context"
"fmt"
"time"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/services/pubsub"
)

// nowTS returns the current time as a TimeStamp using the real wall clock,
// avoiding data races with timeutil.MockUnset during tests.
func nowTS() timeutil.TimeStamp {
return timeutil.TimeStamp(time.Now().Unix())
}

type notificationCountEvent struct {
Type string `json:"type"`
Count int64 `json:"count"`
}

func userTopic(userID int64) string {
return fmt.Sprintf("user-%d", userID)
}

// Init starts the background goroutine that polls notification counts
// and pushes updates to connected WebSocket clients.
func Init() error {
go graceful.GetManager().RunWithShutdownContext(run)
return nil
}
Comment thread
silverwind marked this conversation as resolved.

func run(ctx context.Context) {
ctx, _, finished := process.GetManager().AddTypedContext(ctx, "Service: WebSocket", process.SystemProcessType, true)
defer finished()

if setting.UI.Notification.EventSourceUpdateTime <= 0 {
return
}

then := nowTS().Add(-2)
timer := time.NewTicker(setting.UI.Notification.EventSourceUpdateTime)
defer timer.Stop()
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated

for {
select {
case <-ctx.Done():
return
case <-timer.C:
now := nowTS().Add(-2)

uidCounts, err := activities_model.GetUIDsAndNotificationCounts(ctx, then, now)
Comment thread
mohammad-rj marked this conversation as resolved.
Outdated
if err != nil {
log.Error("websocket: GetUIDsAndNotificationCounts: %v", err)
continue
}

for _, uidCount := range uidCounts {
msg, err := json.Marshal(notificationCountEvent{
Type: "notification-count",
Count: uidCount.Count,
})
if err != nil {
continue
}
pubsub.DefaultBroker.Publish(userTopic(uidCount.UserID), msg)
}

then = now
}
}
}
45 changes: 13 additions & 32 deletions web_src/js/features/notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {logoutFromWorker} from '../modules/worker.ts';
const {appSubUrl, notificationSettings, assetVersionEncoded} = window.config;
let notificationSequenceNumber = 0;

async function receiveUpdateCount(event: MessageEvent<{type: string, data: string}>) {
async function receiveUpdateCount(event: MessageEvent<{type: string, count: number}>) {
try {
const data = JSON.parse(event.data.data);
for (const count of document.querySelectorAll('.notification_count')) {
count.classList.toggle('tw-hidden', data.Count === 0);
count.textContent = `${data.Count}`;
const {count} = event.data;
for (const el of document.querySelectorAll('.notification_count')) {
el.classList.toggle('tw-hidden', count === 0);
el.textContent = `${count}`;
}
await updateNotificationTable();
} catch (error) {
Expand All @@ -21,65 +21,46 @@ async function receiveUpdateCount(event: MessageEvent<{type: string, data: strin
export function initNotificationCount() {
if (!document.querySelector('.notification_count')) return;

let usingPeriodicPoller = false;
const startPeriodicPoller = (timeout: number, lastCount?: number) => {
if (timeout <= 0 || !Number.isFinite(timeout)) return;
usingPeriodicPoller = true;
lastCount = lastCount ?? getCurrentCount();
setTimeout(async () => {
await updateNotificationCountWithCallback(startPeriodicPoller, timeout, lastCount);
}, timeout);
};

if (notificationSettings.EventSourceUpdateTime > 0 && window.EventSource && window.SharedWorker) {
// Try to connect to the event source via the shared worker first
const worker = new SharedWorker(`${window.__webpack_public_path__}js/eventsource.sharedworker.js?v=${assetVersionEncoded}`, 'notification-worker');
if (notificationSettings.EventSourceUpdateTime > 0 && window.SharedWorker) {
// Connect via WebSocket SharedWorker (one connection shared across all tabs)
const wsUrl = `${window.location.origin}${appSubUrl}/-/ws`.replace(/^http/, 'ws');
const worker = new SharedWorker(`${window.__webpack_public_path__}js/websocket.sharedworker.js?v=${assetVersionEncoded}`, 'notification-worker');
worker.addEventListener('error', (event) => {
console.error('worker error', event);
});
worker.port.addEventListener('messageerror', () => {
console.error('unable to deserialize message');
});
worker.port.postMessage({
type: 'start',
url: `${window.location.origin}${appSubUrl}/user/events`,
});
worker.port.addEventListener('message', (event: MessageEvent<{type: string, data: string}>) => {
worker.port.postMessage({type: 'start', url: wsUrl});
worker.port.addEventListener('message', (event: MessageEvent<{type: string, count: number, message?: string}>) => {
if (!event.data || !event.data.type) {
console.error('unknown worker message event', event);
return;
}
if (event.data.type === 'notification-count') {
receiveUpdateCount(event); // no await
} else if (event.data.type === 'no-event-source') {
// browser doesn't support EventSource, falling back to periodic poller
if (!usingPeriodicPoller) startPeriodicPoller(notificationSettings.MinTimeout);
} else if (event.data.type === 'error') {
console.error('worker port event error', event.data);
} else if (event.data.type === 'logout') {
if (event.data.data !== 'here') {
return;
}
worker.port.postMessage({
type: 'close',
});
worker.port.postMessage({type: 'close'});
worker.port.close();
logoutFromWorker();
} else if (event.data.type === 'close') {
worker.port.postMessage({
type: 'close',
});
worker.port.close();
}
});
worker.port.addEventListener('error', (e) => {
console.error('worker port error', e);
});
worker.port.start();
window.addEventListener('beforeunload', () => {
worker.port.postMessage({
type: 'close',
});
worker.port.postMessage({type: 'close'});
worker.port.close();
});

Expand Down
Loading
Loading