Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions app/controllers/api/v1/syncs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

class Api::V1::SyncsController < Api::V1::BaseController
include Pagy::Backend

before_action :ensure_read_scope
before_action :set_sync, only: [ :show ]
Comment thread
JSONbored marked this conversation as resolved.

def index
@per_page = safe_per_page_param
@pagy, @syncs = pagy(
family_syncs_query.preload(:syncable, :children).ordered,
page: safe_page_param,
limit: @per_page
)
Comment thread
coderabbitai[bot] marked this conversation as resolved.

render :index
end

def latest
@sync = family_syncs_query.preload(:syncable, :children).ordered.first
return render json: { data: nil } unless @sync

render :show
end
Comment thread
coderabbitai[bot] marked this conversation as resolved.

def show
render :show
end

private

def set_sync
raise ActiveRecord::RecordNotFound unless valid_uuid?(params[:id])

@sync = family_syncs_query.preload(:syncable, :children).find(params[:id])
Comment thread
JSONbored marked this conversation as resolved.
end

def ensure_read_scope
authorize_scope!(:read)
end

def family_syncs_query
Sync.for_family(Current.family, resource_owner: Current.user)
end
end
49 changes: 48 additions & 1 deletion app/models/sync.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Sync < ApplicationRecord
belongs_to :parent, class_name: "Sync", optional: true
has_many :children, class_name: "Sync", foreign_key: :parent_id, dependent: :destroy

scope :ordered, -> { order(created_at: :desc) }
scope :ordered, -> { order(created_at: :desc, id: :desc) }
scope :incomplete, -> { where("syncs.status IN (?)", %w[pending syncing]) }
scope :visible, -> { incomplete.where("syncs.created_at > ?", VISIBLE_FOR.ago) }

Expand Down Expand Up @@ -57,6 +57,53 @@ class << self
def clean
incomplete.where("syncs.created_at < ?", STALE_AFTER.ago).find_each(&:mark_stale!)
end

def for_family(family, resource_owner: nil)
query = where(syncable_type: "Family", syncable_id: family.id)
query = query.or(where(syncable_type: "Account", syncable_id: account_syncable_ids(family, resource_owner)))

family_syncable_associations.each do |association|
query = query.or(
where(syncable_type: association.klass.name, syncable_id: family.public_send(association.name).select(:id))
)
end

query
end

private
def account_syncable_ids(family, resource_owner)
(resource_owner ? resource_owner.accessible_accounts : family.accounts)
.where(family_id: family.id)
.select(:id)
end

def family_syncable_associations
Family.reflect_on_all_associations(:has_many).select do |association|
association.name.to_s.end_with?("_items") &&
association.klass.included_modules.include?(Syncable)
rescue NameError
false
end
end
end

def in_progress?
pending? || syncing?
end

def terminal?
completed? || failed? || stale?
end

def api_error_payload
return unless failed? || stale?
return if stale? && error.blank?

{
present: true,
message: stale? ? "Sync became stale before completion" : "Sync failed"
}
end

def perform
Expand Down
24 changes: 24 additions & 0 deletions app/views/api/v1/syncs/_sync.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

syncable = sync.syncable

json.id sync.id
json.status sync.status
json.in_progress sync.in_progress?
json.terminal sync.terminal?
json.syncable do
json.type sync.syncable_type
json.id sync.syncable_id
json.name syncable&.try(:name)
end
json.parent_id sync.parent_id
json.children_count sync.children.size
json.window_start_date sync.window_start_date
json.window_end_date sync.window_end_date
json.pending_at sync.pending_at
json.syncing_at sync.syncing_at
json.completed_at sync.completed_at
json.failed_at sync.failed_at
json.error sync.api_error_payload
json.created_at sync.created_at
json.updated_at sync.updated_at
12 changes: 12 additions & 0 deletions app/views/api/v1/syncs/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

json.data do
json.array! @syncs, partial: "api/v1/syncs/sync", as: :sync
end

json.meta do
json.page @pagy.page
json.per_page @per_page
json.total_count @pagy.count
json.total_pages @pagy.pages
end
9 changes: 9 additions & 0 deletions app/views/api/v1/syncs/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

json.data do
if @sync
json.partial! "api/v1/syncs/sync", sync: @sync
else
json.nil!
end
Comment thread
JSONbored marked this conversation as resolved.
end
5 changes: 4 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,10 @@
resource :usage, only: [ :show ], controller: :usage
resource :balance_sheet, only: [ :show ], controller: :balance_sheet
resource :family_settings, only: [ :show ], controller: :family_settings
post :sync, to: "sync#create"
post :sync, to: "sync#create", as: :sync_job
resources :syncs, only: [ :index, :show ] do
get :latest, on: :collection
end

resources :chats, only: [ :index, :show, :create, :update, :destroy ] do
resources :messages, only: [ :create ] do
Expand Down
Loading
Loading