Update immich data importing service

This commit is contained in:
Eugene Burmakin 2024-09-08 16:52:35 +02:00
parent 63336f2126
commit d5cbae620e
12 changed files with 43 additions and 28 deletions

View file

@ -10,7 +10,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Changed ### Changed
- Default value for `RAILS_MAX_THREADS` was changed to 10. - Default value for `RAILS_MAX_THREADS` was changed to 10.
- Visit suggestions background job was moved to its own low priority queue to prevent it from blocking other jobs.
### Fixed
- The Imports page now loading faster.
## [0.13.4] — 2024-09-06 ## [0.13.4] — 2024-09-06

File diff suppressed because one or more lines are too long

View file

@ -5,7 +5,12 @@ class ImportsController < ApplicationController
before_action :set_import, only: %i[show destroy] before_action :set_import, only: %i[show destroy]
def index def index
@imports = current_user.imports.order(created_at: :desc).page(params[:page]) @imports =
current_user
.imports
.select(:id, :name, :source, :created_at, :points_count)
.order(created_at: :desc)
.page(params[:page])
end end
def show; end def show; end

View file

@ -106,4 +106,10 @@ module ApplicationHelper
def active_tab?(link_path) def active_tab?(link_path)
'tab-active' if current_page?(link_path) 'tab-active' if current_page?(link_path)
end end
def notification_link_color(notification)
return 'text-gray-600' if notification.read?
'text-blue-600'
end
end end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
class VisitSuggestingJob < ApplicationJob class VisitSuggestingJob < ApplicationJob
queue_as :default queue_as :visit_suggesting
def perform(user_ids: [], start_at: 1.day.ago, end_at: Time.current) def perform(user_ids: [], start_at: 1.day.ago, end_at: Time.current)
users = user_ids.any? ? User.where(id: user_ids) : User.all users = user_ids.any? ? User.where(id: user_ids) : User.all

View file

@ -8,4 +8,8 @@ class Notification < ApplicationRecord
enum :kind, { info: 0, warning: 1, error: 2 } enum :kind, { info: 0, warning: 1, error: 2 }
scope :unread, -> { where(read_at: nil) } scope :unread, -> { where(read_at: nil) }
def read?
read_at.present?
end
end end

View file

@ -31,7 +31,7 @@ class Areas::Visits::Create
def area_points(area) def area_points(area)
area_radius = area_radius =
if DISTANCE_UNIT.to_sym == :km if ::DISTANCE_UNIT.to_sym == :km
area.radius / 1000.0 area.radius / 1000.0
else else
area.radius / 1609.344 area.radius / 1609.344

View file

@ -13,7 +13,7 @@ class Immich::ImportGeodata
raise ArgumentError, 'Immich API key is missing' if immich_api_key.blank? raise ArgumentError, 'Immich API key is missing' if immich_api_key.blank?
raise ArgumentError, 'Immich URL is missing' if user.settings['immich_url'].blank? raise ArgumentError, 'Immich URL is missing' if user.settings['immich_url'].blank?
immich_data = retrieve_immich_data immich_data = retrieve_immich_data
immich_data_json = parse_immich_data(immich_data) immich_data_json = parse_immich_data(immich_data)
file_name = file_name(immich_data_json) file_name = file_name(immich_data_json)
import = user.imports.find_or_initialize_by(name: file_name, source: :immich_api) import = user.imports.find_or_initialize_by(name: file_name, source: :immich_api)
@ -35,9 +35,9 @@ class Immich::ImportGeodata
end end
def retrieve_immich_data def retrieve_immich_data
(1..12).flat_map do |month_number| 1970.upto(Date.today.year).flat_map do |year|
(1..31).map do |day| (1..12).flat_map do |month_number|
url = "#{immich_api_base_url}/assets/memory-lane?day=#{day}&month=#{month_number}" url = "#{immich_api_base_url}/timeline/bucket?size=MONTH&timeBucket=#{year}-#{month_number}-01"
JSON.parse(HTTParty.get(url, headers:).body) JSON.parse(HTTParty.get(url, headers:).body)
end end
@ -51,25 +51,18 @@ class Immich::ImportGeodata
end end
def parse_immich_data(immich_data) def parse_immich_data(immich_data)
geodata = [] geodata = immich_data.map do |asset|
log_no_data and next if asset_invalid?(asset)
next unless valid?(asset)
immich_data.each do |memory_lane| extract_geodata(asset)
log_no_data and next if memory_lane_invalid?(memory_lane)
assets = extract_assets(memory_lane)
assets.each { |asset| geodata << extract_geodata(asset) if valid?(asset) }
end end
geodata.sort_by { |data| data[:timestamp] } geodata.compact.sort_by { |data| data[:timestamp] }
end end
def memory_lane_invalid?(memory_lane) def asset_invalid?(bucket)
memory_lane.is_a?(Hash) && memory_lane['statusCode'] == 404 bucket.is_a?(Hash) && bucket['statusCode'] == 404
end
def extract_assets(memory_lane)
memory_lane.flat_map { |lane| lane['assets'] }.compact
end end
def extract_geodata(asset) def extract_geodata(asset)

View file

@ -1,7 +1,7 @@
<div role="<%= notification.kind %>" class="<%= notification.kind %> shadow-lg p-5 flex justify-between items-center mb-4 rounded-lg bg-base-200" id="<%= dom_id notification %>"> <div role="<%= notification.kind %>" class="<%= notification.kind %> shadow-lg p-5 flex justify-between items-center mb-4 rounded-lg bg-base-200" id="<%= dom_id notification %>">
<div class="flex-1"> <div class="flex-1">
<h3 class="font-bold text-xl"> <h3 class="font-bold text-xl">
<%= link_to notification.title, notification, class: 'link hover:no-underline text-blue-600' %> <%= link_to notification.title, notification, class: "link hover:no-underline #{notification_link_color(notification)}" %>
</h3> </h3>
<div class="text-sm text-gray-500"><%= time_ago_in_words notification.created_at %> ago</div> <div class="text-sm text-gray-500"><%= time_ago_in_words notification.created_at %> ago</div>

View file

@ -3,7 +3,9 @@
<div class="text-center mb-6"> <div class="text-center mb-6">
<h1 class="font-bold text-4xl mb-4">Notifications</h1> <h1 class="font-bold text-4xl mb-4">Notifications</h1>
<div class="flex items-center justify-center mb-4"> <div class="flex items-center justify-center mb-4">
<%= link_to "Mark all as read", mark_notifications_as_read_path, method: :post, data: { turbo_method: :post }, class: "btn btn-sm btn-primary" %> <% if @notifications.unread.any? %>
<%= link_to "Mark all as read", mark_notifications_as_read_path, method: :post, data: { turbo_method: :post }, class: "btn btn-sm btn-primary" %>
<% end %>
</div> </div>
<div class="mb-4"> <div class="mb-4">
<%= paginate @notifications %> <%= paginate @notifications %>

View file

@ -18,8 +18,8 @@
</div> </div>
<div class="flex items-center"> <div class="flex items-center">
<span class="mr-2">Order by:</span> <span class="mr-2">Order by:</span>
<%= link_to 'Newest', visits_path(order_by: :desc), class: 'btn btn-xs btn-primary mx-1' %> <%= link_to 'Newest', visits_path(order_by: :desc, status: params[:status]), class: 'btn btn-xs btn-primary mx-1' %>
<%= link_to 'Oldest', visits_path(order_by: :asc), class: 'btn btn-xs btn-primary mx-1' %> <%= link_to 'Oldest', visits_path(order_by: :asc, status: params[:status]), class: 'btn btn-xs btn-primary mx-1' %>
</div> </div>
</div> </div>

View file

@ -6,3 +6,4 @@
- exports - exports
- stats - stats
- reverse_geocoding - reverse_geocoding
- visit_suggesting