Skip to content

Commit 36db829

Browse files
Copilotstritti
andcommitted
Fix code review issues: RecordId conversion, CLOSE handling, race conditions, and unused imports
Co-authored-by: stritti <184547+stritti@users.noreply.github.com>
1 parent c756e30 commit 36db829

6 files changed

Lines changed: 54 additions & 16 deletions

File tree

src/app/component/event-card-list/event-card-list.component.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,18 @@ export class EventCardListComponent {
5252
constructor() {
5353
// Effect to trigger data loading when inputs change
5454
// PERFORMANCE FIX: Don't use async in effects, use queueMicrotask instead
55+
// Re-read signals inside microtask to avoid stale values
5556
effect(() => {
56-
const loc = this.location()
57-
const currentId = this.currentEventId()
57+
// Trigger the effect when inputs change
58+
this.location()
59+
this.currentEventId()
5860

5961
// Queue the async work to avoid blocking the effect
6062
queueMicrotask(() => {
63+
// Re-read the signals to get current values
64+
const loc = this.location()
65+
const currentId = this.currentEventId()
66+
6167
if (loc && currentId) {
6268
void this.loadEventsFromLocation(loc, currentId)
6369
} else if (!loc && !currentId) {

src/app/component/event-card/event-card.component.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, input, signal, effect, inject, DestroyRef, computed } from '@angular/core'
1+
import { ChangeDetectionStrategy, Component, input, signal, effect, inject, computed } from '@angular/core'
22
import { CommonModule } from '@angular/common'
33
import { RouterModule } from '@angular/router'
44
import { Event, EventType } from '../../models/event.interface'
@@ -38,7 +38,6 @@ export class EventCardComponent {
3838
private readonly locationService = inject(LocationService)
3939
private readonly localStorageService = inject(LocalStorageService)
4040
private readonly mediaService = inject(MediaService)
41-
private readonly destroyRef = inject(DestroyRef)
4241

4342
// Local state as signals
4443
protected readonly location = signal<Location | null>(null)
@@ -67,7 +66,7 @@ export class EventCardComponent {
6766
const ev = this.event()
6867
if (ev?.id) {
6968
this.resetResolved()
70-
const id = ev.id as unknown as string
69+
const id = this.surrealDBService.recordIdToString(ev.id)
7170
this.isSaved.set(this.localStorageService.isEventSaved(id))
7271
// Use queueMicrotask to avoid blocking the main thread
7372
queueMicrotask(() => {
@@ -84,7 +83,7 @@ export class EventCardComponent {
8483
effect(() => {
8584
this.localStorageService.savedEventsSignal()
8685
const ev = this.event()
87-
const id = (ev?.id as unknown as string) ?? null
86+
const id = ev?.id ? this.surrealDBService.recordIdToString(ev.id) : null
8887
this.isSaved.set(id ? this.localStorageService.isEventSaved(id) : false)
8988
})
9089
}

src/app/component/event-type-pill/event-type-pill.component.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ export class EventTypePillComponent {
2828

2929
// Local state
3030
protected readonly pill = signal<Pill | null>(null)
31+
32+
// Version counter to prevent race conditions
33+
private buildVersion = 0
3134

3235
constructor() {
3336
// Effect to rebuild pill when event changes
@@ -47,7 +50,16 @@ export class EventTypePillComponent {
4750
return
4851
}
4952

53+
// Increment version to invalidate any in-flight requests
54+
const currentVersion = ++this.buildVersion
55+
5056
const allEventType = await this.eventService.getAllEventTypes()
57+
58+
// Check if this is still the latest request
59+
if (currentVersion !== this.buildVersion) {
60+
return // Ignore stale response
61+
}
62+
5163
const eventType = allEventType.find((et) => et.id.id === event.event_type?.id)
5264

5365
if (!eventType?.name) {

src/app/component/snack-bar/snack-bar.component.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export class SnackBarComponent {
8585
}
8686
this.visible.set(false)
8787
}
88+
8889
getTypeClass(): string {
8990
switch (this.type()) {
9091
case 'success':
@@ -112,8 +113,4 @@ export class SnackBarComponent {
112113
return 'M8 16A8 8 0 108 0a8 8 0 000 16zm1-11a1 1 0 10-2 0v4a1 1 0 102 0V5zm-1 9a1 1 0 100-2 1 1 0 000 2z'
113114
}
114115
}
115-
116-
close(): void {
117-
this.visible.set(false)
118-
}
119116
}

src/app/pages/favourites/favourites.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ChangeDetectionStrategy, Component, OnInit, inject, effect, signal } from '@angular/core'
22

33
import { Event } from '../../models/event.interface'
4-
import { Router, RouterLink } from '@angular/router'
4+
import { RouterLink } from '@angular/router'
55
import { FavoriteService } from '../../services/favorite.service'
66
import { EventCardComponent } from '../../component/event-card/event-card.component'
77
import { TranslateModule } from '@ngx-translate/core'
@@ -29,7 +29,6 @@ export class FavouritesComponent implements OnInit {
2929
protected readonly loading = signal(true)
3030

3131
private readonly favoriteService = inject(FavoriteService)
32-
private readonly router = inject(Router)
3332

3433
constructor() {
3534
// Effect um auf Änderungen zu reagieren

src/app/services/surrealdb.service.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ export class SurrealdbService extends Surreal {
3535
super()
3636
}
3737

38-
private recordIdToString(recordId: RecordId<string> | StringRecordId): string {
38+
/**
39+
* Convert a RecordId to a string representation.
40+
* Public method to be used by components for consistent RecordId handling.
41+
*/
42+
recordIdToString(recordId: RecordId<string> | StringRecordId): string {
3943
const asString = (recordId as unknown as { toString?: () => string })?.toString?.()
4044
if (typeof asString === 'string') {
4145
return asString
@@ -312,9 +316,19 @@ export class SurrealdbService extends Surreal {
312316
const queryUuid = await super.live<T>(
313317
table,
314318
(action, result) => {
315-
const update: LiveQueryUpdate<T> = {
316-
action: action as 'CREATE' | 'UPDATE' | 'DELETE',
317-
result: result as T
319+
// Handle all possible actions including CLOSE
320+
let update: LiveQueryUpdate<T>
321+
322+
if (action === 'CLOSE') {
323+
update = { action: 'CLOSE' }
324+
// Clean up on CLOSE
325+
this.liveQueryCallbacks.delete(queryKey)
326+
this.liveQueryUuids.delete(queryKey)
327+
} else {
328+
update = {
329+
action: action as 'CREATE' | 'UPDATE' | 'DELETE',
330+
result: result as T
331+
}
318332
}
319333

320334
// Notify all callbacks for this query
@@ -331,6 +345,17 @@ export class SurrealdbService extends Surreal {
331345
this.liveQueryUuids.set(queryKey, queryUuid)
332346
} catch (error) {
333347
console.error('Failed to create live query:', error)
348+
// Notify listeners of failure via CLOSE event
349+
const update: LiveQueryUpdate<T> = { action: 'CLOSE' }
350+
const callbacks = this.liveQueryCallbacks.get(queryKey)
351+
if (callbacks) {
352+
callbacks.forEach(callback => {
353+
(callback as LiveQueryCallback<T>)(update)
354+
})
355+
}
356+
// Clean up
357+
this.liveQueryCallbacks.delete(queryKey)
358+
this.liveQueryUuids.delete(queryKey)
334359
throw error
335360
}
336361
}

0 commit comments

Comments
 (0)