Skip to content

Commit

Permalink
fix: grpcws data race and unit creation race condition
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Trost <[email protected]>
  • Loading branch information
galexrt committed Oct 6, 2024
1 parent 5ce8819 commit 7fe713c
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 56 deletions.
100 changes: 60 additions & 40 deletions app/components/centrum/dispatches/DispatchStatusInfoPopover.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
<script lang="ts" setup>
import DispatchDetailsByIDSlideover from '~/components/centrum/dispatches//DispatchDetailsByIDSlideover.vue';
import { useCentrumStore } from '~/store/centrum';
import type { DispatchStatus } from '~~/gen/ts/resources/centrum/dispatches';
import { StatusDispatch } from '~~/gen/ts/resources/centrum/dispatches';
import { dispatchStatusToBGColor } from '../helpers';
defineProps<{
const props = defineProps<{
status: DispatchStatus | undefined;
}>();
const modal = useModal();
const centrumStore = useCentrumStore();
const dispatch = props.status?.dispatchId ? centrumStore.dispatches.get(props.status.dispatchId) : undefined;
const dispatchStatusColor = computed(() => dispatchStatusToBGColor(props.status?.status));
</script>

<template>
Expand All @@ -18,45 +25,58 @@ const modal = useModal();
<slot name="after" />
</span>
</template>
<template v-else>
<UPopover>
<UButton
variant="outline"
:padded="false"
size="xs"
class="inline-flex items-center p-0.5"
trailing-icon="i-mdi-chevron-down"
>
<slot name="before" />
<span> DSP-{{ status.dispatchId }} </span>
<slot name="after" />
</UButton>

<template #panel>
<div class="p-4">
<div class="mb-2 flex items-center gap-2">
<UButton
variant="link"
icon="i-mdi-car-emergency"
:title="$t('common.detail', 2)"
@click="
modal.open(DispatchDetailsByIDSlideover, {
dispatchId: status.dispatchId,
})
"
>
{{ $t('common.detail', 2) }}
</UButton>
</div>
<div class="text-gray-900 dark:text-white">
<p class="text-base font-semibold leading-none">DSP-{{ status.dispatchId }}</p>
<p class="inline-flex items-center justify-center text-sm font-normal">
<span class="font-semibold"> {{ $t('common.status') }} </span>:
{{ $t(`enums.centrum.StatusDispatch.${StatusDispatch[status.status ?? 0]}`) }}
<UPopover v-else>
<UButton
variant="outline"
:padded="false"
size="xs"
class="inline-flex items-center p-0.5"
trailing-icon="i-mdi-chevron-down"
>
<slot name="before" />
<span> DSP-{{ status.dispatchId }} </span>
<slot name="after" />
</UButton>

<template #panel>
<div class="inline-flex min-w-48 flex-col gap-1 p-4">
<div class="flex items-center gap-2">
<UButton
variant="link"
icon="i-mdi-car-emergency"
:title="$t('common.detail', 2)"
@click="
modal.open(DispatchDetailsByIDSlideover, {
dispatchId: status.dispatchId,
})
"
>
{{ $t('common.detail', 2) }}
</UButton>
</div>

<p class="text-base font-semibold leading-none text-gray-900 dark:text-white">DSP-{{ status.dispatchId }}</p>

<UBadge class="rounded font-semibold" :class="dispatchStatusColor" size="xs">
{{ $t(`enums.centrum.StatusDispatch.${StatusDispatch[status.status ?? 0]}`) }}
</UBadge>
<div v-if="dispatch" class="text-gray-900 dark:text-white">
<p class="text-sm font-medium leading-none">
{{ $t('common.unit', 2) }}
</p>
<template v-if="dispatch.units.length === 0">
<p class="text-xs font-normal">
{{ $t('common.units', 0) }}
</p>
</div>
</template>
<ul v-else class="inline-flex flex-col text-xs font-normal">
<li v-for="unit in dispatch.units" :key="unit.unitId" class="inline-flex items-center gap-1">
<span>{{ unit.unit?.initials }}: {{ unit.unit?.name }}</span>
</li>
</ul>
</div>
</template>
</UPopover>
</template>
</div>
</template>
</UPopover>
</template>
17 changes: 13 additions & 4 deletions app/components/centrum/units/UnitInfoPopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import PhoneNumberBlock from '~/components/partials/citizens/PhoneNumberBlock.vue';
import { useCentrumStore } from '~/store/centrum';
import type { DispatchAssignment } from '~~/gen/ts/resources/centrum/dispatches';
import type { Unit } from '~~/gen/ts/resources/centrum/units';
import { StatusUnit, type Unit } from '~~/gen/ts/resources/centrum/units';
import { unitStatusToBGColor } from '../helpers';
const centrumStore = useCentrumStore();
const { timeCorrection } = storeToRefs(centrumStore);
withDefaults(
const props = withDefaults(
defineProps<{
unit: Unit | undefined;
initialsOnly?: boolean;
Expand All @@ -18,6 +19,8 @@ withDefaults(
assignment: undefined,
},
);
const unitStatusColor = computed(() => unitStatusToBGColor(props.unit?.status?.status));
</script>

<template>
Expand All @@ -44,8 +47,13 @@ withDefaults(
</UButton>
<template #panel>
<div class="p-4">
<div class="inline-flex min-w-48 flex-col gap-1 p-4">
<p class="text-base font-semibold leading-none">{{ unit.name }} ({{ unit.initials }})</p>
<UBadge class="rounded font-semibold" :class="unitStatusColor" size="xs">
{{ $t(`enums.centrum.StatusUnit.${StatusUnit[unit.status?.status ?? 0]}`) }}
</UBadge>
<p v-if="assignment?.expiresAt" class="inline-flex items-center justify-center text-sm font-normal">
{{
useLocaleTimeAgo(toDate(assignment.expiresAt, timeCorrection), {
Expand All @@ -54,13 +62,14 @@ withDefaults(
}).value
}}
</p>
<div class="text-gray-900 dark:text-white">
<p class="text-sm font-medium leading-none">
{{ $t('common.members') }}
</p>
<template v-if="unit.users.length === 0">
<p class="text-xs font-normal">
{{ $t('common.units', 0) }}
{{ $t('common.member', 0) }}
</p>
</template>
<ul v-else class="inline-flex flex-col text-xs font-normal">
Expand Down
24 changes: 13 additions & 11 deletions gen/go/proto/services/centrum/manager/units.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ func (s *Manager) UpdateUnitAssignments(ctx context.Context, job string, userId
X: x,
Y: y,
Postal: postal,
}); err != nil {
}, true); err != nil {
return nil, false, err
}

Expand Down Expand Up @@ -305,7 +305,7 @@ func (s *Manager) UpdateUnitAssignments(ctx context.Context, job string, userId
X: x,
Y: y,
Postal: postal,
}); err != nil {
}, true); err != nil {
return nil, false, err
}

Expand All @@ -326,7 +326,7 @@ func (s *Manager) UpdateUnitAssignments(ctx context.Context, job string, userId
X: x,
Y: y,
Postal: postal,
}); err != nil {
}, true); err != nil {
return nil, false, err
}
}
Expand Down Expand Up @@ -398,7 +398,7 @@ func (s *Manager) CreateUnit(ctx context.Context, job string, unit *centrum.Unit
CreatedAt: timestamp.Now(),
UnitId: uint64(lastId),
Status: centrum.StatusUnit_STATUS_UNIT_UNAVAILABLE,
}); err != nil {
}, false); err != nil {
return nil, err
}

Expand Down Expand Up @@ -479,7 +479,7 @@ func (s *Manager) UpdateUnit(ctx context.Context, job string, unit *centrum.Unit
return unit, nil
}

func (s *Manager) AddUnitStatus(ctx context.Context, tx qrm.DB, job string, status *centrum.UnitStatus) (*centrum.UnitStatus, error) {
func (s *Manager) AddUnitStatus(ctx context.Context, tx qrm.DB, job string, status *centrum.UnitStatus, publish bool) (*centrum.UnitStatus, error) {
tUnitStatus := table.FivenetCentrumUnitsStatus
stmt := tUnitStatus.
INSERT(
Expand Down Expand Up @@ -522,13 +522,15 @@ func (s *Manager) AddUnitStatus(ctx context.Context, tx qrm.DB, job string, stat
return nil, err
}

data, err := proto.Marshal(status)
if err != nil {
return nil, err
}
if publish {
data, err := proto.Marshal(status)
if err != nil {
return nil, err
}

if _, err := s.js.Publish(ctx, eventscentrum.BuildSubject(eventscentrum.TopicUnit, eventscentrum.TypeUnitStatus, job), data); err != nil {
return nil, err
if _, err := s.js.Publish(ctx, eventscentrum.BuildSubject(eventscentrum.TopicUnit, eventscentrum.TypeUnitStatus, job), data); err != nil {
return nil, err
}
}

return newStatus, nil
Expand Down
11 changes: 10 additions & 1 deletion pkg/grpc/grpcws/websocket_channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,16 @@ func (w *WebsocketChannel) ping() {
return
case <-w.timer.C:
w.timer.Reset(w.timeOutInterval)
w.activeStreams[0].channel.write(framePingResponse)
func() {
w.mutex.Lock()
defer w.mutex.Unlock()

stream, ok := w.activeStreams[0]
if !ok {
return
}
stream.channel.write(framePingResponse)
}()
}
}
}
Expand Down

0 comments on commit 7fe713c

Please sign in to comment.