Slow API Call any help?
I call the api for some lifestyle nutrition objects using the bellow and it returns 700 objects. Its currently taking 25-30secs. The lifestyle items do not have any attachments so don't understand why the call takes so long.
removing the attachments from the jbuilder file returns the API call in 8-12 secs. Am I missing something?
I have the following models:
# == Schema Information
#
# Table name: lifestyle_nutritions
#
# id :bigint not null, primary key
# due_date :datetime
# last_activity :datetime
# created_at :datetime not null
# updated_at :datetime not null
# client_id :bigint not null
# lifestyle_plan_id :bigint
#
# Indexes
#
# index_lifestyle_nutritions_on_client_id (client_id)
# index_lifestyle_nutritions_on_lifestyle_plan_id (lifestyle_plan_id)
#
# Foreign Keys
#
# fk_rails_... (client_id => clients.id)
# fk_rails_... (lifestyle_plan_id => lifestyle_plans.id)
#
class LifestyleNutrition < ApplicationRecord
belongs_to :client
belongs_to :lifestyle_plan, optional: true
has_many :lifestyle_nutrition_items, dependent: :destroy
accepts_nested_attributes_for :lifestyle_nutrition_items, allow_destroy: true
has_many :lifestyle_comments, dependent: :destroy
scope :lifestyle_nutrition_between, ->(range) { where(due_date: range )}
scope :not_overdue_lifestyle_nutrition, ->(timezone) { where('due_date >= ?', timezone ? Time.now.in_time_zone(timezone).to_date : Date.today) }
scope :future_lifestyle_nutrition, ->(timezone) { not_overdue_lifestyle_nutrition(timezone) }
scope :future_lifestyle_nutrition_between, ->(range, timezone) { lifestyle_nutrition_between(range).future_lifestyle_nutrition(timezone) }
scope :overdue_lifestyle_nutrition, ->(timezone) { where('due_date < ?', timezone ? Time.now.in_time_zone(timezone).to_date : Date.today) }
scope :past_lifestyle_nutrition, ->(timezone) { overdue_lifestyle_nutrition(timezone) }
scope :past_lifestyle_nutrition_between, ->(range, timezone) { lifestyle_nutrition_between(range).past_lifestyle_nutrition(timezone) }
scope :nutritions_between, ->(range) { where(due_date: range )}
def complete?
lifestyle_nutrition_items.count === lifestyle_nutrition_items.actioned.count
end
def state
if client
timezone = client.user.timezone
status = complete? ? "complete" : "pending"
if due_date
if status === "complete"
"complete"
elsif status === "pending" && due_date < (timezone ? Time.now.in_time_zone(timezone).to_date : Date.today)
"missed"
else
"pending"
end
else
"pending"
end
end
end
end
# == Schema Information
#
# Table name: lifestyle_nutrition_items
#
# id :bigint not null, primary key
# completed :boolean
# notes :text
# notification_sent :boolean default(FALSE)
# notification_time :datetime
# notification_time_string :string
# prescription_description :text
# created_at :datetime not null
# updated_at :datetime not null
# lifestyle_nutrition_id :bigint not null
# lifestyle_prescription_id :bigint not null
# lifestyle_type_id :bigint not null
#
# Indexes
#
# index_lifestyle_nutrition_items_on_lifestyle_nutrition_id (lifestyle_nutrition_id)
# index_lifestyle_nutrition_items_on_lifestyle_prescription_id (lifestyle_prescription_id)
# index_lifestyle_nutrition_items_on_lifestyle_type_id (lifestyle_type_id)
#
# Foreign Keys
#
# fk_rails_... (lifestyle_nutrition_id => lifestyle_nutritions.id)
# fk_rails_... (lifestyle_prescription_id => lifestyle_prescriptions.id)
# fk_rails_... (lifestyle_type_id => lifestyle_types.id)
#
class LifestyleNutritionItem < ApplicationRecord
belongs_to :lifestyle_nutrition
belongs_to :lifestyle_type
belongs_to :lifestyle_prescription
has_many :attachments, as: :attachable, dependent: :destroy
scope :completed, -> { where(completed: true) }
scope :actioned, -> { where.not(completed: nil) }
before_destroy :destroy_notifications
before_save :set_notification_time
def destroy_notifications
self.lifestyle_nutrition.client.coach.notifications.where(type: "LifestyleNotification").each do |n|
if (n.params[:lifestyle_nutrition_item][:id] == self.id)
n.destroy
end
end
end
def set_notification_time
if notification_time_string.present?
date = lifestyle_nutrition.due_date
self.notification_time = get_notification_time(date, notification_time_string)
end
end
def get_notification_time(date, time)
notification_send_time = date
hours = time.split(":")[0].to_i
mins = time.split(":")[1].to_i
notification_send_time = notification_send_time.advance(hours: hours)
if mins > 0
notification_send_time = notification_send_time.advance(minutes: mins)
end
if lifestyle_nutrition.client.user.timezone.present?
notification_send_time = notification_send_time.in_time_zone(lifestyle_nutrition.client.user.timezone)
else
notification_send_time = notification_send_time.in_time_zone("London")
end
notification_send_time -= notification_send_time.utc_offset
notification_send_time = notification_send_time.utc
end
end
# == Schema Information
#
# Table name: attachments
#
# id :bigint not null, primary key
# attachable_type :string
# attachment_url :string
# cleaned_up :boolean default(FALSE)
# converted :boolean default(FALSE)
# copied :boolean default(FALSE)
# file_type :string
# name :string
# original_url :string
# size :integer
# created_at :datetime not null
# updated_at :datetime not null
# attachable_id :integer
#
class Attachment < ApplicationRecord
before_create :set_original_url
after_create :uploadcare
belongs_to :attachable, polymorphic: true
def isVideo?
vid = file_type.split("/")[0]
vid === "video"
end
def mp4?
mp4 = file_type.split("/")[1]
mp4 === "mp4"
end
def needsConverting?
isVideo?
end
private
def set_original_url
self.original_url = attachment_url
end
def uploadcare
UploadcareJob.set(wait: 1.minute).perform_later(id)
end
end
Jbuilder file.
json.lifestyle_nutritions @lifestyle_nutritions.each do |lifestyle|
json.id lifestyle.id
json.due_date lifestyle.due_date.strftime('%Y/%m/%d')
json.lifestyle_plan_id lifestyle.lifestyle_plan_id
json.lifestyle_nutrition_items_attributes lifestyle.lifestyle_nutrition_items.order(:created_at).each do |item|
json.id item.id
json.lifestyle_type item.lifestyle_type.name
json.lifestyle_type_id item.lifestyle_type_id
json.lifestyle_prescription item.lifestyle_prescription.name
json.lifestyle_prescription_id item.lifestyle_prescription_id
json.notification_time item.notification_time
json.notification_time_string item.notification_time_string
json.prescription_description item.prescription_description
json.notes item.notes
json.completed item.completed
json.attachments item.attachments do |attachment|
json.id attachment.id
json.attachment_url attachment.attachment_url
json.file_type attachment.file_type
end
end
json.comments lifestyle.lifestyle_comments.order(:created_at).each do |comment|
json.id comment.id
json.lifestyle_nutrition_id comment.lifestyle_nutrition_id
json.body comment.body
json.created_at comment.created_at
json.commentable_type comment.commentable_type
json.commenter_name comment.commentable_type == "Client" ? comment.commentable.name : comment.commentable.user.name
json.commenter_initials comment.commentable && comment.commentable.name ? comment.commentable.name.initials : ""
json.avatar_url comment.commentable && comment.commentable.user.avatar ? comment.commentable.user.avatar.url : nil
json.attachments comment.attachments do |attachment|
json.id attachment.id
json.attachment_url attachment.attachment_url
json.file_type attachment.file_type
end
end
end