mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
Fix last sample sync issue by making slice boundaries inclusive
Changed boundary checks from exclusive [start, end) to inclusive [start, end] to ensure samples occurring exactly at slice boundaries are synced correctly. This fixes the issue where the last sample in the database would never get synced because it was filtered out by the exclusive end boundary check while the sync state advanced to its timestamp. Affected syncers: - AbstractTimeSampleSyncer (HRV, SpO2, Weight, etc.) - StepsSyncer - HeartRateSyncer - SleepSyncer
This commit is contained in:
+2
-1
@@ -102,7 +102,8 @@ internal abstract class AbstractTimeSampleSyncer<TSample : TimeSample, TRecord :
|
|||||||
|
|
||||||
val recordsToInsert = samples.filter {
|
val recordsToInsert = samples.filter {
|
||||||
val timestamp = Instant.ofEpochMilli(it.timestamp)
|
val timestamp = Instant.ofEpochMilli(it.timestamp)
|
||||||
if (timestamp.isBefore(sliceStartBoundary) || !timestamp.isBefore(sliceEndBoundary)) {
|
// Use inclusive boundaries [sliceStart, sliceEnd] to ensure last sample is included
|
||||||
|
if (timestamp.isBefore(sliceStartBoundary) || timestamp.isAfter(sliceEndBoundary)) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Skipping sample for at {} as it's outside the slice {} - {}.",
|
"Skipping sample for at {} as it's outside the slice {} - {}.",
|
||||||
timestamp,
|
timestamp,
|
||||||
|
|||||||
+2
-2
@@ -77,8 +77,8 @@ internal object HeartRateSyncer : ActivitySampleSyncer {
|
|||||||
for (gbSample in validHRSamples) {
|
for (gbSample in validHRSamples) {
|
||||||
val currentSampleTimestamp = Instant.ofEpochSecond(gbSample.timestamp.toLong())
|
val currentSampleTimestamp = Instant.ofEpochSecond(gbSample.timestamp.toLong())
|
||||||
|
|
||||||
// Ensure sample is strictly within the slice [sliceStartBoundary, sliceEndBoundary)
|
// Use inclusive boundaries [sliceStart, sliceEnd] for the slice
|
||||||
if (currentSampleTimestamp.isBefore(sliceStartBoundary) || !currentSampleTimestamp.isBefore(sliceEndBoundary)) {
|
if (currentSampleTimestamp.isBefore(sliceStartBoundary) || currentSampleTimestamp.isAfter(sliceEndBoundary)) {
|
||||||
skippedCount++
|
skippedCount++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -122,8 +122,9 @@ internal object SleepSyncer : ContextualActivitySampleSyncer {
|
|||||||
val sessionBoundaryStart = analysisSession.sleepStart.toInstant()
|
val sessionBoundaryStart = analysisSession.sleepStart.toInstant()
|
||||||
val sessionBoundaryEndInclusive = analysisSession.sleepEnd.toInstant()
|
val sessionBoundaryEndInclusive = analysisSession.sleepEnd.toInstant()
|
||||||
|
|
||||||
// Check if session overlaps with the current slice
|
// Check if session overlaps with the current slice (inclusive boundaries [sliceStart, sliceEnd])
|
||||||
if (!sessionBoundaryStart.isBefore(sliceEndBoundary) || !sessionBoundaryEndInclusive.isAfter(sliceStartBoundary)) {
|
// Skip if: sessionStart > sliceEnd OR sessionEnd < sliceStart
|
||||||
|
if (sessionBoundaryStart.isAfter(sliceEndBoundary) || sessionBoundaryEndInclusive.isBefore(sliceStartBoundary)) {
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
"Skipping sleep session (identified by SleepAnalysis) for device '{}' (Timeframe: {} to {}) as it does not overlap with current slice ({} to {}).",
|
"Skipping sleep session (identified by SleepAnalysis) for device '{}' (Timeframe: {} to {}) as it does not overlap with current slice ({} to {}).",
|
||||||
deviceName,
|
deviceName,
|
||||||
|
|||||||
+3
-2
@@ -69,8 +69,9 @@ internal object StepsSyncer : ActivitySampleSyncer {
|
|||||||
val endTs = Instant.ofEpochSecond(currentSample.timestamp.toLong())
|
val endTs = Instant.ofEpochSecond(currentSample.timestamp.toLong())
|
||||||
val startTs = endTs.minus(1, ChronoUnit.MINUTES)
|
val startTs = endTs.minus(1, ChronoUnit.MINUTES)
|
||||||
|
|
||||||
// Ensure the record's interval [startTs, endTs) overlaps with the slice [sliceStartBoundary, sliceEndBoundary)
|
// Use inclusive boundaries [sliceStart, sliceEnd] for the slice
|
||||||
if (endTs.isAfter(sliceStartBoundary) && startTs.isBefore(sliceEndBoundary)) {
|
// Overlap check: interval overlaps if endTs > sliceStart AND startTs <= sliceEnd
|
||||||
|
if (endTs.isAfter(sliceStartBoundary) && !startTs.isAfter(sliceEndBoundary)) {
|
||||||
stepsRecordList.add(StepsRecord(startTs, offset, endTs, offset, stepsInMinute, metadata))
|
stepsRecordList.add(StepsRecord(startTs, offset, endTs, offset, stepsInMinute, metadata))
|
||||||
} else {
|
} else {
|
||||||
skippedCount++
|
skippedCount++
|
||||||
|
|||||||
Reference in New Issue
Block a user