Sync endpoint

pull/1022/head
Rick Carlino 2018-10-20 19:25:39 -05:00
parent 084dc420e3
commit 8c4dc8d56f
5 changed files with 126 additions and 0 deletions

View File

@ -30,6 +30,10 @@ module Api
send_emails ? email_data_dump : store_data_dump
end
def sync
mutate Devices::Sync.run(device: current_device)
end
private
# Store the JSON on the local filesystem for self hosted users that don't

View File

@ -0,0 +1,37 @@
module Devices
class Sync < Mutations::Command
FIELDS = [ :id, :updated_at ]
PLURAL = [ :diagnostic_dumps,
:farm_events,
:farmware_envs,
:farmware_installations,
:peripherals,
:pin_bindings,
:points,
:regimens,
:sensor_readings,
:sensors,
:sequences,
:tools ]
required do
model :device, class: Device
end
def execute
base = { now: Time.now.utc, # Clock skew detector?
device: pluck(device),
fbos_config: pluck(device.fbos_config),
firmware_config: pluck(device.firmware_config), }
PLURAL.reduce(base) do |json, resource|
json.update(resource => device.send(resource).pluck(*FIELDS))
end
end
private
def pluck(obj)
[[obj.id, obj.updated_at]]
end
end
end

View File

@ -54,6 +54,7 @@ FarmBot::Application.routes.draw do
end
get "/global_config" => "global_config#show", as: :global_config
get "/device/sync" => "devices#sync", as: :device_sync
# Make life easier on API users by not adding special rules for singular
# resources.

View File

@ -0,0 +1,57 @@
require 'spec_helper'
describe Api::DevicesController do
include Devise::Test::ControllerHelpers
let(:user) { FactoryBot.create(:user) }
let(:device) { user.device }
describe '#sync' do
it 'provides timestamps of updates, plus current time' do
sign_in user
FactoryBot.create(:diagnostic_dump, device: device)
FactoryBot.create(:farm_event, device: device)
FactoryBot.create(:farmware_env, device: device)
FactoryBot.create(:farmware_installation, device: device)
FactoryBot.create(:generic_pointer, device: device)
FactoryBot.create(:peripheral, device: device)
FactoryBot.create(:pin_binding, device: device)
FactoryBot.create(:plant, device: device)
FactoryBot.create(:regimen, device: device)
FactoryBot.create(:sensor_reading, device: device)
FactoryBot.create(:sensor, device: device)
FactoryBot.create(:tool_slot, device: device)
FactoryBot.create(:tool, device: device)
FakeSequence.create(device: device)
get :sync, params: {}, session: { format: :json }
expect(response.status).to eq(200)
expect(Time.now - Time.parse(json[:now])).to be < 150
pair = json[:device].first
expect(pair.first).to eq(device.id)
expect(pair.last).to eq(device.updated_at.as_json)
expect(pair.last.first(8)).to eq(device.updated_at.as_json.first(8))
json.keys.without(:now).without(:device).map do |key|
array = json[key]
expect(array).to be_kind_of(Array)
sample = array.sample
raise "Needs #{key} entry" unless sample
expect(sample).to be_kind_of(Array)
expect(sample.first).to be_kind_of(Integer)
expect(sample.last).to be_kind_of(String)
obj = device.send(key)
if obj.is_a?(ApplicationRecord)
expect(obj.id).to eq(sample.first)
expect(obj.updated_at.as_json).to eq(sample.last)
else
pairs = obj
.pluck(:id, :updated_at)
.map{|(id, date)| [id, date.as_json]}
expect(json[key]).to eq(pairs)
end
end
end
end
end

View File

@ -0,0 +1,27 @@
require 'spec_helper'
describe Devices::Sync do
let(:user) { FactoryBot.create(:user) }
let(:device) { user.device }
it 'is different this time!' do
results = Devices::Sync.run!(device: device)
expect(results.keys.sort).to eq([ :device,
:diagnostic_dumps,
:farm_events,
:farmware_envs,
:farmware_installations,
:fbos_config,
:firmware_config,
:now,
:peripherals,
:pin_bindings,
:points,
:regimens,
:sensor_readings,
:sensors,
:sequences,
:tools ])
end
end