public static void MaybeRemakeWebRoleData() { var webrole_sentinel_uri = BlobStorage.MakeAzureBlobUri("admin", CalendarAggregator.Configurator.webrole_sentinel, false); if (BlobStorage.ExistsBlob(webrole_sentinel_uri)) { var list = HttpUtils.FetchUrl(webrole_sentinel_uri).DataAsString(); GenUtils.LogMsg("status", "worker role remaking wrd for " + list, null); var args = new Dictionary<string, string>(); WebRoleData.MakeWebRoleData(); bs.DeleteBlob("admin", CalendarAggregator.Configurator.webrole_sentinel); } }
protected void Application_Start() { var msg = "WebRole: Application_Start"; GenUtils.PriorityLogMsg("info", msg, null); ElmcityApp.wrd = WebRoleData.GetWrd(); ElmcityApp.RegisterRoutes(RouteTable.Routes, ElmcityApp.wrd); GenUtils.PriorityLogMsg("info", RouteTable.Routes.Count + " routes registered", null); Utils.ScheduleTimer(PurgeCache, CalendarAggregator.Configurator.webrole_cache_purge_interval_minutes, name: "PurgeCache", startnow: false); Utils.ScheduleTimer(ReloadSettingsAndRoutes, minutes: CalendarAggregator.Configurator.webrole_reload_interval_minutes, name: "ReloadSettingsAndRoutes", startnow: true); Utils.ScheduleTimer(MakeTablesAndCharts, minutes: CalendarAggregator.Configurator.web_make_tables_and_charts_interval_minutes, name: "MakeTablesAndCharts", startnow: false); ElmcityUtils.Monitor.TryStartMonitor(CalendarAggregator.Configurator.process_monitor_interval_minutes, CalendarAggregator.Configurator.process_monitor_table); }
public static void _ReloadSettingsAndRoutes() { GenUtils.LogMsg("status", "webrole _ReloadRoutes", null); bool new_routes = false; try { var settings = GenUtils.GetSettingsFromAzureTable(); if (settings.Keys.Count == 0) { GenUtils.PriorityLogMsg("exception", "ReloadSettings: no settings!", null); } else { ElmcityController.settings = settings; } } catch (Exception e0) { var msg = "_ReloadSettingsAndRoutes: settings"; GenUtils.PriorityLogMsg("exception", msg, e0.Message); } try { var themes = Utils.GetThemesDict(); if (ObjectUtils.DictOfDictStrEqualsDictOfDictStr(themes, ElmcityController.themes) == false) { GenUtils.LogMsg("status", "_ReloadSettingsAndRoutes", "reloading themes"); lock (ElmcityController.themes) { ElmcityController.themes = themes; } } } catch (Exception e2) { var msg = "_ReloadSettingsAndRoutes: themes"; GenUtils.PriorityLogMsg("exception", msg, e2.Message); } return; try { var new_wrd = WebRoleData.GetWrd(); if (new_wrd == null || wrd.IsConsistent() == false) { GenUtils.PriorityLogMsg("warning", "null or inconsistent WebRoleData!", null); return; } if (new_wrd.ready_ids.Count != ElmcityApp.wrd.ready_ids.Count) // did # of hubs change? either on initial load or subsequently { new_routes = true; // force rebuild of route map GenUtils.LogMsg("status", "Reload: found a new hub", null); WebRoleData.SaveTimestampedWrd(ElmcityApp.wrd); lock (ElmcityApp.wrd) { ElmcityApp.wrd = new_wrd; // update WebRoleData (todo: rewarm caches affected) } } foreach (var id in ElmcityApp.wrd.ready_ids) // did any hub's renderer change? { var cached_renderer = ElmcityApp.wrd.renderers[id]; var current_renderer = Utils.AcquireRenderer(id); if (cached_renderer.timestamp != current_renderer.timestamp) // timestamp changed { if (!Utils.RenderersAreEqual(cached_renderer, current_renderer, except_keys: new List <string>() { "timestamp" })) { GenUtils.LogMsg("status", "Reload: new renderer for " + id, null); lock (ElmcityApp.wrd) { ElmcityApp.wrd.renderers[id] = current_renderer; // update the renderer if (ElmcityApp.home_controller != null) // skip this if we found a change on startup, controller not ready { var cache = new AspNetCache(ElmcityApp.home_controller.HttpContext.Cache); var url = Utils.MakeBaseZonelessUrl(id); cache.Remove(url); // flush cached objects for id var obj = HttpUtils.FetchUrl(new Uri(url)); // rewarm cache } } } } } } catch (Exception e1) { GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: cannot check/update wrd", e1.Message + e1.StackTrace); } if (new_routes) { var existing_routes = RouteTable.Routes; var route_count = existing_routes.Count; try { GenUtils.LogMsg("status", "_ReloadSettingsAndRoutes: registering " + route_count + " routes", null); lock (RouteTable.Routes) { var route_count_old = RouteTable.Routes.Count; GenUtils.PriorityLogMsg("info", RouteTable.Routes.Count + " routes before reload", null); RouteTable.Routes.Clear(); ElmcityApp.RegisterRoutes(RouteTable.Routes, ElmcityApp.wrd); GenUtils.PriorityLogMsg("info", RouteTable.Routes.Count + " routes registered", null); var route_count_new = RouteTable.Routes.Count; if (route_count_new < route_count_old) { GenUtils.PriorityLogMsg("warning", "route count was " + route_count_old + ", is " + route_count_new, null); } } } catch (Exception e3) { GenUtils.PriorityLogMsg("exception", "_ReloadSettingsAndRoutes: registering " + route_count + " routes", e3.Message + e3.StackTrace); ElmcityApp.RegisterRoutes(existing_routes, ElmcityApp.wrd); } } }
public static void RegisterRoutes(RouteCollection routes, WebRoleData wrd) { GenUtils.LogMsg("status", "RegisterRoutes", "ready_ids: " + wrd.ready_ids.Count()); #region HomeController routes.MapRoute( "AnnArborChronicle", "AnnArborChronicle", new { controller = "Home", action = "AnnArborChronicle" } ); routes.MapRoute( "add_to_cal", "add_to_cal", new { controller = "Home", action = "add_to_cal" } ); routes.MapRoute( "add_fb_event", "add_fb_event", new { controller = "Home", action = "add_fb_event" } ); routes.MapRoute( "description_from_title_and_dtstart", "{id}/description_from_title_and_dtstart", new { controller = "Home", action = "description_from_title_and_dtstart" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "description_from_uid", "{id}/description_from_uid", new { controller = "Home", action = "description_from_uid" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "description_from_hash", "{id}/description_from_hash", new { controller = "Home", action = "description_from_hash" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "DiscardMisfoldedDescriptionsAndBogusCategoriesThenAddEasternVTIMEZONE", "DiscardMisfoldedDescriptionsAndBogusCategoriesThenAddEasternVTIMEZONE", new { controller = "Home", action = "DiscardMisfoldedDescriptionsAndBogusCategoriesThenAddEasternVTIMEZONE" } ); routes.MapRoute( "facebook_auth", "facebook_auth", new { controller = "Home", action = "facebook_auth" } ); routes.MapRoute( "feed2json", "{id}/feed2json", new { controller = "Home", action = "feed2json" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "get_css_theme", "get_css_theme", new { controller = "Home", action = "get_css_theme" } ); /* * // target for facebook oauth redirect, used periodically to refresh fb api access token * todo: revisit in light of fb offline_access transition * routes.MapRoute( * "fb_access", * "fb_access", * new { controller = "Home", action = "fb_access" } * ); */ routes.MapRoute( "get_editable_metadata", "services/{id}/get_editable_metadata", new { controller = "Home", action = "get_editable_metadata" }, new { id = wrd.str_ready_ids } ); // alias routes.MapRoute( "edit", "services/{id}/edit", new { controller = "Home", action = "get_editable_metadata" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "get_fb_ical_url", "get_fb_ical_url", new { controller = "Home", action = "get_fb_ical_url" } ); routes.MapRoute( "get_blob", "get_blob", new { controller = "Home", action = "get_blob" } ); routes.MapRoute( "get_form_post_ical_url", "get_form_post_ical_url", new { controller = "Home", action = "get_form_post_ical_url" } ); routes.MapRoute( "get_csv_ical_url", "get_csv_ical_url", new { controller = "Home", action = "get_csv_ical_url" } ); routes.MapRoute( "get_high_school_sports_url", "get_high_school_sports_url/{school}/{tz}", new { controller = "Home", action = "get_high_school_sports_url" }, new { tz = "ET|CT|MT|PT|AT|HT" } ); routes.MapRoute( "get_ics_to_ics_ical_url", "get_ics_to_ics_ical_url", new { controller = "Home", action = "get_ics_to_ics_ical_url" } ); routes.MapRoute( "get_rss_xcal_ical_url", "get_rss_xcal_ical_url", new { controller = "Home", action = "get_rss_xcal_ical_url" } ); routes.MapRoute( "get_ical_url_from_eventbrite_event_page", "get_ical_url_from_eventbrite_event_page", new { controller = "Home", action = "get_ical_url_from_eventbrite_event_page" } ); routes.MapRoute( "get_ical_url_from_eid_of_eventbrite_event_page", "get_ical_url_from_eid_of_eventbrite_event_page", new { controller = "Home", action = "get_ical_url_from_eid_of_eventbrite_event_page" } ); routes.MapRoute( "get_json_metadata", "services/{id}/get_json_metadata", new { controller = "Home", action = "get_json_metadata" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "google_auth", "google_auth", new { controller = "Home", action = "google_auth" } ); routes.MapRoute( "home", "", new { controller = "Home", action = "index" } ); routes.MapRoute( "events3", "{id}", new { controller = "Services", action = "GetEvents", type = "html" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "about", "{id}/about", new { controller = "Home", action = "about" }, new { id = wrd.str_ready_ids } ); // parse csv, return ics routes.MapRoute( "ics_from_csv", "ics_from_csv", new { controller = "Home", action = "ics_from_csv" } ); // return ics filtered by after, before, include_keyword, or exclude_keyword routes.MapRoute( "ics_from_ics", "ics_from_ics", new { controller = "Home", action = "ics_from_ics" } ); // parse facebook page events, return ics routes.MapRoute( "ics_from_fb_page", "ics_from_fb_page", new { controller = "Home", action = "ics_from_fb_page" } ); // ical from a lastfm venue id routes.MapRoute( "ics_from_lastfm_venue", "ics_from_lastfm_venue", new { controller = "Home", action = "ics_from_lastfm_venue" } ); // parse atom+vcal, return ics routes.MapRoute( "ics_from_vcal", "ics_from_vcal", new { controller = "Home", action = "ics_from_vcal" } ); // search eventbrite by name and location, return ics feed routes.MapRoute( "ics_from_eventbrite_organizer", "ics_from_eventbrite_organizer", new { controller = "Home", action = "ics_from_eventbrite_organizer" } ); // list eventbrite events by organizer, return ics feed routes.MapRoute( "ics_from_eventbrite_organizer_id", "ics_from_eventbrite_organizer_id", new { controller = "Home", action = "ics_from_eventbrite_organizer_id" } ); // get an ical for a single eventbrite id routes.MapRoute( "ics_from_eventbrite_eid", "ics_from_eventbrite_eid", new { controller = "Home", action = "ics_from_eventbrite_eid" } ); // parse rss+xcal, return ics routes.MapRoute( "ics_from_xcal", "ics_from_xcal", new { controller = "Home", action = "ics_from_xcal" } ); // parse the findlocal feed, return ics routes.MapRoute( "ics_from_findlocal", "ics_from_findlocal", new { controller = "Home", action = "ics_from_findlocal" } ); /* parse this format: * [ * { * "dtstart": "2013-04-10T18:00:00", * "dtend": "2013-04-10T21:00:00", * "categories": "music", * "title": "Trout rehearsal", * "url": "http://www.applehill.org", * "source": "Apple Hill Center for Chamber Music", * "allday": false, * "lat": "42.977274,", * "lon": "-72.175455", * "description": "", * "location": "" * } * ] */ routes.MapRoute( "ics_from_json", "ics_from_json", new { controller = "Home", action = "ics_from_json" } ); // convert ics to json routes.MapRoute( "ics_to_json", "ics_to_json", new { controller = "Home", action = "ics_to_json" } ); // convert ics to json routes.MapRoute( "ics_via_form_post", "ics_via_form_post", new { controller = "Home", action = "ics_via_form_post" } ); routes.MapRoute( "ics_from_nasa_iss_tracking_rss", "ics_from_nasa_iss_tracking_rss", new { controller = "Home", action = "ics_from_nasa_iss_tracking_rss" } ); routes.MapRoute( "keep_only_vevents", "keep_only_vevents", new { controller = "Home", action = "keep_only_vevents" } ); routes.MapRoute( "live_auth", "live_auth", new { controller = "Home", action = "live_auth" } ); routes.MapRoute( "map", "{id}/map", new { controller = "Home", action = "map" }, new { id = wrd.str_ready_ids } ); // visualize changes between two json snapshots (flavor feeds is list of dicts, flavor metadata is single dict) // http://elmcity.cloudapp.net/services/elmcity/meta_history?id=elmcity&flavor=feeds&a_name=elmcity.2011.07.25.00.56.feeds.json&b_name=elmcity.2011.07.25.10.00.feeds.json // http://elmcity.cloudapp.net/services/elmcity/meta_history?id=elmcity&flavor=metadata&a_name=elmcity.2011.07.25.00.56.metadata.json&b_name=elmcity.2011.07.25.10.00.metadata.json routes.MapRoute( "meta_history", "services/{id}/meta_history", new { controller = "Home", action = "meta_history" }, new { id = wrd.str_ready_ids } ); // events happening now + offset routes.MapRoute( "soon", "{id}/{type}/soon", new { controller = "Home", action = "soon" }, new { id = wrd.str_ready_ids, type = "html|rss|ics|xml|json" } ); routes.MapRoute( "put_image_selections", "put_image_selections", new { controller = "Home", action = "put_image_selections" } ); routes.MapRoute( "put_json_metadata", "services/{id}/put_json_metadata", new { controller = "Home", action = "put_json_metadata" }, new { id = wrd.str_ready_ids } ); routes.MapRoute( "put_json_feeds", "services/{id}/put_json_feeds", new { controller = "Home", action = "put_json_feeds" }, new { id = wrd.str_ready_ids } ); // dump a snapshot of diagnostic data routes.MapRoute( "snapshot", "snapshot", new { controller = "Home", action = "snapshot" } ); // query the query-safe tables routes.MapRoute( "table_query", "table_query/{table}", new { controller = "Home", action = "table_query" }, new { table = ElmcityController.settings["query_safe_tables"] } ); // get the static json tag cloud routes.MapRoute( "tag_cloud", "{id}/tag_cloud", new { controller = "Home", action = "tag_cloud" }, new { id = wrd.str_ready_ids } ); // fetch plain text of an ical feed, optionally grepped by property routes.MapRoute( "text_from_ics", "text_from_ics", new { controller = "Home", action = "text_from_ics" } ); // url helpers page routes.MapRoute( "url_helpers", "url_helpers", new { controller = "Home", action = "url_helpers" } ); // alias routes.MapRoute( "helpers", "helpers", new { controller = "Home", action = "helpers" } ); routes.MapRoute( "twitter_auth", "twitter_auth", new { controller = "Home", action = "twitter_auth" } ); routes.MapRoute( "view_calendar", "view_calendar", new { controller = "Home", action = "view_calendar" } ); routes.MapRoute( "welcome", "welcome", new { controller = "Home", action = "welcome" } ); #endregion #region ServicesController // this pattern covers most uses. gets events for a given hub id in many formats. allows // only the specified formats, and only hub ids that are "ready" routes.MapRoute( "events", "services/{id}/{type}", new { controller = "Services", action = "GetEvents" }, new { id = wrd.str_ready_ids, type = get_events_param_types } ); // also allow bare id/type routes.MapRoute( "events2", "{id}/{type}", new { controller = "Services", action = "GetEvents" }, new { id = wrd.str_ready_ids, type = get_events_param_types } ); routes.MapRoute( "logs", "logs", new { controller = "Services", action = "GetLogEntries" } ); // dump the hub's metadata, extended with computed values, routes.MapRoute( "metadata", "services/{id}/metadata", new { controller = "Services", action = "GetMetadata" }, new { id = wrd.str_ready_ids } ); // alternate at root routes.MapRoute( "metadata2", "{id}/metadata", new { controller = "Services", action = "GetMetadata" }, new { id = wrd.str_ready_ids } ); // used by worker to remove pickled objects from cache after an aggregator run // todo: protect this endpoint routes.MapRoute( "remove", "services/remove_cache_entry", new { controller = "Services", action = "RemoveCacheEntry" } ); routes.MapRoute( "viewcache", "services/viewcache", new { controller = "Services", action = "ViewCache" } ); // performance monitor data as an odata feed routes.MapRoute( "odata", "services/odata", new { controller = "Services", action = "GetODataFeed" } ); // entry point for the fusecal system: runs fusecal.py which dispatches to an // html-or-rss-or-ics to ics parser for myspace, librarything, libraryinsight, etc. routes.MapRoute( "fusecal", "services/fusecal", new { controller = "Services", action = "GetFusecalICS" } ); // see http://blog.jonudell.net/2009/11/09/where-is-the-money-going/ routes.MapRoute( "arra", "arra", new { controller = "Services", action = "GetArraData" } ); routes.MapRoute( "call_twitter_api", "services/call_twitter_api", new { controller = "Services", action = "CallTwitterApi" } ); #endregion GenUtils.LogMsg("status", routes.Count() + " routes", null); }