Files
dawarich/app/services/tracks/point_loaders/incremental_loader.rb
2025-07-07 21:48:07 +02:00

73 lines
2.3 KiB
Ruby

# frozen_string_literal: true
module Tracks
module PointLoaders
class IncrementalLoader
attr_reader :user, :day, :redis_buffer
def initialize(user, day = nil)
@user = user
@day = day || Date.current
@redis_buffer = Tracks::RedisBuffer.new(user.id, @day)
end
def load_points
# Get buffered points from Redis
buffered_points = redis_buffer.retrieve
# Find the last track for this day to determine where to start
last_track = Track.last_for_day(user, day)
# Load new points since last track
new_points = load_new_points_since_last_track(last_track)
# Combine buffered points with new points
combined_points = merge_points(buffered_points, new_points)
Rails.logger.debug "Loaded #{buffered_points.size} buffered points and #{new_points.size} new points for user #{user.id}"
combined_points
end
private
def load_new_points_since_last_track(last_track)
scope = user.points
.where.not(lonlat: nil)
.where.not(timestamp: nil)
.where(track_id: nil) # Only process points not already assigned to tracks
if last_track
scope = scope.where('timestamp > ?', last_track.end_at.to_i)
else
# If no last track, load all points for the day
day_start = day.beginning_of_day.to_i
day_end = day.end_of_day.to_i
scope = scope.where('timestamp >= ? AND timestamp <= ?', day_start, day_end)
end
scope.order(:timestamp)
end
def merge_points(buffered_points, new_points)
# Convert buffered point hashes back to Point objects if needed
buffered_point_objects = buffered_points.map do |point_data|
# If it's already a Point object, use it directly
if point_data.is_a?(Point)
point_data
else
# Create a Point-like object from the hash
Point.new(point_data.except('id').symbolize_keys)
end
end
# Combine and sort by timestamp
all_points = (buffered_point_objects + new_points.to_a).sort_by(&:timestamp)
# Remove duplicates based on timestamp and coordinates
all_points.uniq { |point| [point.timestamp, point.lat, point.lon] }
end
end
end
end