public BodymediaUpdater() { super(); ObjectType burn = ObjectType.getObjectType(connector(), "burn"); ObjectType sleep = ObjectType.getObjectType(connector(), "sleep"); ObjectType steps = ObjectType.getObjectType(connector(), "steps"); url.put(burn, "burn/day/minute/intensity/"); url.put(sleep, "sleep/day/period/"); url.put(steps, "step/day/hour/"); maxIncrement.put(burn, 1); maxIncrement.put(sleep, 1); maxIncrement.put(steps, 31); }
/** * Retrieves that history for the given facet from the start date to the end date. It peforms the * api calls in reverse order starting from the end date. This is so that the most recent * information is retrieved first. * * @param updateInfo The api's info * @param ot The ObjectType that represents the facet to be updated * @param start The earliest date for which the burn history is retrieved. This date is included * in the update. * @param end The latest date for which the burn history is retrieved. This date is also included * in the update. * @throws Exception If either storing the data fails or if the rate limit is reached on * Bodymedia's api */ private void retrieveHistory(UpdateInfo updateInfo, ObjectType ot, DateTime start, DateTime end) throws Exception { final String urlExtension = url.get(ot); final int increment = maxIncrement.get(ot); DateTimeComparator comparator = DateTimeComparator.getDateOnlyInstance(); DateTime current = start; // Setup the rate delay if we haven't already Long rateDelay = getRateDelay(updateInfo); try { // Loop from start to end, incrementing by the max number of days you can // specify for a given type of query. This is 1 for burn and sleep, and 31 for steps. // @ loop_invariant date.compareTo(userRegistrationDate) >= 0; while (comparator.compare(current, end) < 0) { if (guestService.getApiKey(updateInfo.apiKey.getId()) == null) { logger.info("Not updating BodyMedia connector instance with a deleted apiKeyId"); return; } String startPeriod = current.toString(formatter); String endPeriod = current.plusDays(increment - 1).toString(formatter); String minutesUrl = "http://api.bodymedia.com/v2/json/" + urlExtension + startPeriod + "/" + endPeriod + "?api_key=" + guestService.getApiKeyAttribute(updateInfo.apiKey, "bodymediaConsumerKey"); // The following call may fail due to bodymedia's api. That is expected behavior enforceRateLimits(rateDelay); String json = signpostHelper.makeRestCall(updateInfo.apiKey, ot.value(), minutesUrl); guestService.setApiKeyAttribute( updateInfo.apiKey, "timeOfLastCall", String.valueOf(System.currentTimeMillis())); JSONObject bodymediaResponse = JSONObject.fromObject(json); JSONArray daysArray = bodymediaResponse.getJSONArray("days"); if (bodymediaResponse.has("lastSync")) { DateTime d = form.parseDateTime(bodymediaResponse.getJSONObject("lastSync").getString("dateTime")); // Get timezone map from UpdateInfo context TimezoneMap tzMap = (TimezoneMap) updateInfo.getContext("tzMap"); // Insert lastSync into the updateInfo context so it's accessible to the updater updateInfo.setContext("lastSync", d); List<AbstractFacet> newFacets = new ArrayList<AbstractFacet>(); for (Object o : daysArray) { if (o instanceof JSONObject) { if (ot == ObjectType.getObjectType(connector(), "steps")) newFacets.add(createOrUpdateStepsFacet((JSONObject) o, updateInfo, d, tzMap)); else if (ot == ObjectType.getObjectType(connector(), "burn")) newFacets.add(createOrUpdateBurnFacet((JSONObject) o, updateInfo, d, tzMap)); else newFacets.add(createOrUpdateSleepFacet((JSONObject) o, updateInfo, d, tzMap)); } } bodyTrackStorageService.storeApiData(updateInfo.getGuestId(), newFacets); } current = current.plusDays(increment); // Update the stored value that controls when we will start updating next time updateStartDate(updateInfo, ot, current); } } catch (Exception e) { StringBuilder sb = new StringBuilder( "module=updateQueue component=updater action=BodymediaUpdater.retrieveHistory") .append(" message=\"exception while retrieving history\" connector=") .append(updateInfo.apiKey.getConnector().toString()) .append(" guestId=") .append(updateInfo.apiKey.getGuestId()) .append(" updatingDate=") .append(current); logger.info(sb.toString()); // Update the stored value that controls when we will start updating next time updateStartDate(updateInfo, ot, current); // Rethrow the error so that this task gets rescheduled throw e; } }