From cb2790379de6e7f769acdafb78c663027e830db4 Mon Sep 17 00:00:00 2001 From: w-le Date: Mon, 24 May 2021 20:55:03 +0800 Subject: [PATCH 1/3] fix(mulesoft/exporter): status vars, perf, style, format --- drivers/mulesoft/calendar_exporter.cr | 82 +++++++++++++-------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/drivers/mulesoft/calendar_exporter.cr b/drivers/mulesoft/calendar_exporter.cr index d732202502..e56ee43b53 100644 --- a/drivers/mulesoft/calendar_exporter.cr +++ b/drivers/mulesoft/calendar_exporter.cr @@ -5,100 +5,97 @@ require "place_calendar" class MuleSoft::CalendarExporter < PlaceOS::Driver descriptive_name "MuleSoft Bookings to Calendar Events Exporter" - generic_name :Bookings - description %(Retrieves and creates bookings using the MuleSoft API) + generic_name :MulesoftExport + description %(Listens for new MuleSoft bookings and creates matching Events in a Calendar) default_settings({ - calendar_time_zone: "Australia/Sydney" + calendar_time_zone: "Australia/Sydney", }) accessor calendar : Calendar_1 @time_zone_string : String | Nil = "Australia/Sydney" @time_zone : Time::Location = Time::Location.load("Australia/Sydney") - @bookings : Array( Hash(String, Int64 | String | Nil) ) = [] of Hash(String, Int64 | String | Nil) + @bookings : Array(Hash(String, Int64 | String | Nil)) = [] of Hash(String, Int64 | String | Nil) @existing_events : Array(JSON::Any) = [] of JSON::Any # An array of Attendee that has only the system (room) email address. Generally static @just_this_system : NamedTuple(email: String, name: String) = {email: "", name: ""} - - def on_load + + def on_load @just_this_system = { "email": system.email.not_nil!, - "name": system.name + "name": system.name, } on_update end def on_update subscriptions.clear - + @time_zone_string = setting?(String, :calendar_time_zone).presence @time_zone = Time::Location.load(@time_zone_string.not_nil!) if @time_zone_string - self[:timezone] = Time.local.to_s + self[:timezone] = @time_zone.to_s subscription = system.subscribe(:Bookings_1, :bookings) do |subscription, mulesoft_bookings| - logger.debug {"DETECTED changed in Mulesoft Bookings.."} - @bookings = Array( Hash(String, Int64 | String | Nil) ).from_json(mulesoft_bookings) - logger.debug {"#{@bookings.size} bookings in total"} + logger.debug { "DETECTED changed in Mulesoft Bookings..." } + @bookings = Array(Hash(String, Int64 | String | Nil)).from_json(mulesoft_bookings) + logger.debug { "#{@bookings.size} bookings in total" } + self[:total_bookings] = @bookings.size update_events - @bookings.each {|b| export_booking(b)} + @bookings.each { |b| export_booking(b) } end end - def status() + def status { "bookings": @bookings, - "events": @existing_events + "events": @existing_events, } end def update_events - logger.debug {"FETCHING existing Calendar events..."} + logger.debug { "FETCHING existing Calendar events..." } @existing_events = fetch_events() - logger.debug {"#{@existing_events.size} events in total"} + logger.debug { "#{@existing_events.size} events in total" } + self[:total_events] = @existing_events.size end protected def fetch_events(past_span : Time::Span = 14.days, future_span : Time::Span = 14.days) now = Time.local @time_zone from = now - past_span - til = now + future_span + til = now + future_span calendar.list_events( - calendar_id: system.email.not_nil!, + calendar_id: system.email.not_nil!, period_start: from.to_unix, - period_end: til.to_unix + period_end: til.to_unix ).get.as_a end - protected def export_booking(booking : Hash(String, Int64 | String | Nil)) - # Mulesoft booking titles are often nil. Use the body instead in this case - booking["title"] = booking["body"] if booking["title"].nil? - booking["title"] = "#{booking["recurring_master_id"]} #{booking["title"]}" - logger.debug {"Checking for existing events that match: #{booking}"} + # Add the course code to the front of the booking title/body + booking["title"] = "#{booking["recurring_master_id"]} #{booking["title"] || booking["body"]}" + logger.debug { "Checking for existing events that match: #{booking}" } unless event_already_exists?(booking, @existing_events) new_event = { - title: booking["title"], - event_start: booking["event_start"], - event_end: booking["event_end"], - timezone: @time_zone_string, - description: booking["body"], - user_id: system.email.not_nil!, - attendees: [@just_this_system], - location: system.name.not_nil! + title: booking["title"], + event_start: booking["event_start"], + event_end: booking["event_end"], + timezone: @time_zone_string, + description: booking["body"], + user_id: system.email.not_nil!, + attendees: [@just_this_system], + location: system.name.not_nil!, } - logger.debug {">>> EXPORTING booking #{new_event}"} + logger.debug { ">>> EXPORTING booking #{new_event}" } calendar.create_event(**new_event) end end protected def event_already_exists?(new_event : Hash(String, Int64 | String | Nil), existing_events : Array(JSON::Any)) - existing_events.each do |existing_event| - return true if events_match?(new_event, existing_event.as_h) - end - false + existing_events.any? { |existing_event| events_match?(new_event, existing_event.as_h) } end protected def events_match?(event_a : Hash(String, Int64 | String | Nil), event_b : Hash(String, JSON::Any)) @@ -107,11 +104,10 @@ class MuleSoft::CalendarExporter < PlaceOS::Driver def delete_all_events(past_days : Int32 = 14, future_days : Int32 = 14) events = fetch_events(past_span: past_days.days, future_span: future_days.days) - event_ids = events.map { |e| e["id"]} - event_ids.each do |event_id| - calendar.delete_event(calendar_id: system.email.not_nil!, event_id: event_id) + events.each do |event| + calendar.delete_event(calendar_id: system.email.not_nil!, event_id: event["id"]) end - "Deleted #{event_ids.size} events" + logger.debug { "DELETED #{events.size} events" } + events.size end - end From 822368e9bcd57745d787cac276f39df56a0a81e8 Mon Sep 17 00:00:00 2001 From: William Le Date: Mon, 24 May 2021 21:41:01 +0800 Subject: [PATCH 2/3] style(mulesoft/exporter): whitespace --- drivers/mulesoft/calendar_exporter.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mulesoft/calendar_exporter.cr b/drivers/mulesoft/calendar_exporter.cr index d28baeb642..177f76d935 100644 --- a/drivers/mulesoft/calendar_exporter.cr +++ b/drivers/mulesoft/calendar_exporter.cr @@ -41,7 +41,7 @@ class MuleSoft::CalendarExporter < PlaceOS::Driver @bookings = Array(Hash(String, Int64 | String | Nil)).from_json(mulesoft_bookings) logger.debug { "#{@bookings.size} bookings in total" } self[:total_bookings] = @bookings.size - + update_events @bookings.each { |b| export_booking(b) } end From c8f3f18595a51e783ddcbdfbf1d2c856da7743b4 Mon Sep 17 00:00:00 2001 From: w-le Date: Fri, 28 May 2021 16:07:38 +0800 Subject: [PATCH 3/3] fix(mulesoft/exporter): clone booking before transform; clearer naming; typo --- drivers/mulesoft/calendar_exporter.cr | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/mulesoft/calendar_exporter.cr b/drivers/mulesoft/calendar_exporter.cr index 177f76d935..d61b6c3091 100644 --- a/drivers/mulesoft/calendar_exporter.cr +++ b/drivers/mulesoft/calendar_exporter.cr @@ -37,7 +37,7 @@ class MuleSoft::CalendarExporter < PlaceOS::Driver self[:timezone] = @time_zone.to_s subscription = system.subscribe(:Bookings_1, :bookings) do |_subscription, mulesoft_bookings| - logger.debug { "DETECTED changed in Mulesoft Bookings..." } + logger.debug { "DETECTED change in Mulesoft Bookings..." } @bookings = Array(Hash(String, Int64 | String | Nil)).from_json(mulesoft_bookings) logger.debug { "#{@bookings.size} bookings in total" } self[:total_bookings] = @bookings.size @@ -73,7 +73,9 @@ class MuleSoft::CalendarExporter < PlaceOS::Driver ).get.as_a end - protected def export_booking(booking : Hash(String, Int64 | String | Nil)) + protected def export_booking(mulesoft_booking : Hash(String, Int64 | String | Nil)) + # The resulting Calendar Event is to be slightly different to the Mulesoft Booking, so clone here and transform + booking = mulesoft_booking.clone # Add the course code to the front of the booking title/body booking["title"] = "#{booking["recurring_master_id"]} #{booking["title"] || booking["body"]}" logger.debug { "Checking for existing events that match: #{booking}" } @@ -89,17 +91,17 @@ class MuleSoft::CalendarExporter < PlaceOS::Driver attendees: [@just_this_system], location: system.name.not_nil!, } - logger.debug { ">>> EXPORTING booking #{new_event}" } + logger.debug { ">>> EXPORTING booking as: #{new_event}" } calendar.create_event(**new_event) end end - protected def event_already_exists?(new_event : Hash(String, Int64 | String | Nil), existing_events : Array(JSON::Any)) - existing_events.any? { |existing_event| events_match?(new_event, existing_event.as_h) } + protected def event_already_exists?(booking : Hash(String, Int64 | String | Nil), existing_events : Array(JSON::Any)) + existing_events.any? { |existing_event| booking_matches_event?(booking, existing_event.as_h) } end - protected def events_match?(event_a : Hash(String, Int64 | String | Nil), event_b : Hash(String, JSON::Any)) - event_a.select("event_start", "event_end", "title") == event_b.select("event_start", "event_end", "title") + protected def booking_matches_event?(booking : Hash(String, Int64 | String | Nil), event : Hash(String, JSON::Any)) + booking.select("event_start", "event_end", "title") == event.select("event_start", "event_end", "title") end def delete_all_events(past_days : Int32 = 14, future_days : Int32 = 14)