Skip to content

Commit

Permalink
add cache to the weather service so we don't spam all our API hits
Browse files Browse the repository at this point in the history
  • Loading branch information
bigboxer23 committed Aug 11, 2023
1 parent 809a85a commit 8dce44b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.bigboxer23.generationMeter;

import com.bigboxer23.generationMeter.data.Device;
import com.bigboxer23.generationMeter.data.Location;
import com.bigboxer23.generationMeter.data.WeatherSystemData;
import java.io.IOException;
import java.util.List;
Expand All @@ -24,8 +23,8 @@ public AlarmComponent(OpenWeatherComponent openWeatherComponent) {
public void fireAlarms(List<Device> devices) throws IOException {
logger.debug("checking alarms");
// TODO: criteria for actually firing
Location location = openWeatherComponent.getLatLongFromCity("golden valley", "mn", 581);
WeatherSystemData sunriseSunset = openWeatherComponent.getSunriseSunset(location.getLat(), location.getLon());
WeatherSystemData sunriseSunset =
openWeatherComponent.getSunriseSunsetFromCityStateCountry("golden valley", "mn", 581);
logger.debug("sunrise/sunset " + sunriseSunset.getSunrise() + "," + sunriseSunset.getSunset());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import com.bigboxer23.generationMeter.data.WeatherData;
import com.bigboxer23.generationMeter.data.WeatherSystemData;
import com.bigboxer23.utils.http.OkHttpUtil;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -33,31 +36,76 @@ public class OpenWeatherComponent {

private final Moshi moshi = new Moshi.Builder().build();

public Location getLatLongFromCity(String city, String state, int countryCode) throws IOException {
logger.info("retrieving lat/long from " + city + " " + state);
try (Response response = OkHttpUtil.getSynchronous(
MessageFormat.format(
kOpenWeatherMapCityToLatLong, city + "," + state + "," + countryCode, openWeatherMapAPIKey),
null)) {
String body = response.body().string();
logger.debug("lat/long body " + body);
JsonAdapter<List<Location>> jsonAdapter =
moshi.adapter(Types.newParameterizedType(List.class, Location.class));
return Optional.ofNullable(jsonAdapter.fromJson(body))
.map(loc -> loc.isEmpty() ? null : loc.get(0))
.orElse(null);
}
private Cache<String, WeatherSystemData> weatherCache =
CacheBuilder.newBuilder().expireAfterAccess(3, TimeUnit.DAYS).build();

private Cache<String, Location> locationCache =
CacheBuilder.newBuilder().expireAfterAccess(30, TimeUnit.DAYS).build();

protected Location getLatLongFromCity(String city, String state, int countryCode) {
return Optional.ofNullable(locationCache.getIfPresent(city + state + countryCode))
.map(loc -> {
logger.debug("retrieving lat/long (cached) from " + city + " " + state);
loc.setFromCache(true);
return loc;
})
.orElseGet(() -> {
logger.info("retrieving lat/long from " + city + " " + state);
try (Response response = OkHttpUtil.getSynchronous(
MessageFormat.format(
kOpenWeatherMapCityToLatLong,
city + "," + state + "," + countryCode,
openWeatherMapAPIKey),
null)) {
String body = response.body().string();
logger.debug("lat/long body " + body);
JsonAdapter<List<Location>> jsonAdapter =
moshi.adapter(Types.newParameterizedType(List.class, Location.class));
Location location = Optional.ofNullable(jsonAdapter.fromJson(body))
.map(loc -> loc.isEmpty() ? null : loc.get(0))
.orElse(null);
if (location != null) {
locationCache.put(city + state + countryCode, location);
}
return location;
} catch (IOException e) {
logger.error("getLatLongFromCity", e);
}
return null;
});
}

protected WeatherSystemData getSunriseSunset(double latitude, double longitude) {
return Optional.ofNullable(weatherCache.getIfPresent(latitude + ":" + longitude))
.map(loc -> {
logger.debug("retrieving weather (cached) from " + latitude + ":" + longitude);
loc.setFromCache(true);
return loc;
})
.orElseGet(() -> {
logger.debug("Fetching OpenWeatherMap data");
try (Response response = OkHttpUtil.getSynchronous(
MessageFormat.format(kOpenWeatherMapUrl, latitude, longitude, openWeatherMapAPIKey),
null)) {
String body = response.body().string();
logger.debug("weather body " + body);
WeatherSystemData data = Optional.ofNullable(
moshi.adapter(WeatherData.class).fromJson(body))
.map(WeatherData::getSys)
.orElse(null);
if (data != null) {
weatherCache.put(latitude + ":" + longitude, data);
}
return data;
} catch (IOException e) {
logger.error("getSunriseSunset", e);
}
return null;
});
}

public WeatherSystemData getSunriseSunset(double latitude, double longitude) throws IOException {
logger.debug("Fetching OpenWeatherMap data");
try (Response response = OkHttpUtil.getSynchronous(
MessageFormat.format(kOpenWeatherMapUrl, latitude, longitude, openWeatherMapAPIKey), null)) {
String body = response.body().string();
logger.debug("weather body " + body);
return Optional.ofNullable(moshi.adapter(WeatherData.class).fromJson(body))
.map(WeatherData::getSys)
.orElse(null);
}
public WeatherSystemData getSunriseSunsetFromCityStateCountry(String city, String state, int countryCode) {
Location location = getLatLongFromCity(city, state, countryCode);
return getSunriseSunset(location.getLat(), location.getLon());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ public class Location {
private double lat;

private double lon;

private boolean fromCache = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ public class WeatherSystemData {
private int sunrise;

private int sunset;

private boolean fromCache = false;
}

0 comments on commit 8dce44b

Please sign in to comment.