primitive clustering, cache nominatim

This commit is contained in:
Will Freeman
2024-10-29 19:45:30 -06:00
parent fdae715409
commit 0680fcb908
8 changed files with 204 additions and 43 deletions
@@ -97,10 +97,19 @@ object ShotgunServer {
val bindingFuture = Http().newServerAt("0.0.0.0", 8080).bind(routes)
println(s"Server now online. Please navigate to http://localhost:8080\nPress RETURN to stop...")
StdIn.readLine() // let it run until user presses return
// Handle the binding future properly
bindingFuture.foreach { binding =>
println(s"Server online at http://localhost:${binding.localAddress.getPort}/")
println("Press RETURN to stop...")
}
StdIn.readLine()
bindingFuture
.flatMap(_.unbind()) // trigger unbinding from the port
.onComplete(_ => system.terminate()) // and shutdown when done
.flatMap(_.unbind())
.onComplete { _ =>
println("Server shutting down...")
system.terminate()
}
}
}
@@ -6,27 +6,48 @@ import pekko.http.scaladsl.Http
import pekko.http.scaladsl.model._
import pekko.http.scaladsl.unmarshalling.Unmarshal
import spray.json._
import scala.collection.mutable
import scala.concurrent.{ExecutionContextExecutor, Future}
class NominatimClient(implicit val system: ActorSystem, implicit val executionContext: ExecutionContextExecutor) {
val baseUrl = "https://nominatim.openstreetmap.org/search"
private val cache: mutable.LinkedHashMap[String, JsValue] = new mutable.LinkedHashMap[String, JsValue]()
private val maxCacheSize = 300
private def cleanUpCache(): Unit = {
if (cache.size > maxCacheSize) {
val oldest = cache.head
cache.remove(oldest._1)
}
}
def geocodePhrase(query: String): Future[JsValue] = {
val request = HttpRequest(
uri = s"$baseUrl?q=$query&format=json",
headers = List(headers.`User-Agent`("DeFlock/1.0"))
)
cleanUpCache()
cache.get(query) match {
case Some(cachedResult) =>
println(s"Cache hit for $query")
Future.successful(cachedResult)
case _ =>
println(s"Cache miss for $query")
val request = HttpRequest(
uri = s"$baseUrl?q=$query&format=json",
headers = List(headers.`User-Agent`("DeFlock/1.0"))
)
Http().singleRequest(request).flatMap { response =>
response.status match {
case StatusCodes.OK =>
Unmarshal(response.entity).to[String].map { jsonString =>
jsonString.parseJson
Http().singleRequest(request).flatMap { response =>
response.status match {
case StatusCodes.OK =>
Unmarshal(response.entity).to[String].map { jsonString =>
val json = jsonString.parseJson
cache.put(query, json)
json
}
case _ =>
response.discardEntityBytes()
Future.failed(new Exception(s"Failed to geocode phrase: ${response.status}"))
}
case _ =>
response.discardEntityBytes()
Future.failed(new Exception(s"Failed to geocode phrase: ${response.status}"))
}
}
}
}
}