Cleanup fileservice and dataservice

This commit is contained in:
Guntis Smaukstelis
2023-12-17 22:48:24 +02:00
parent 578fdd778f
commit 2aa6c5f43c
12 changed files with 73 additions and 379 deletions
-1
View File
@@ -20,7 +20,6 @@ object DBConnection {
val raw = URI.create(url)
val name = raw.getPath.substring(1)
println("")
val dbUrl = s"jdbc:postgresql://${raw.getHost}:${raw.getPort}${raw.getPath}?${raw.getQuery}"
val username = raw.getUserInfo.split(":")(0)
val password = raw.getUserInfo.split(":")(1)
-108
View File
@@ -1,108 +0,0 @@
package db
import cats.effect.unsafe.implicits.global
import cats.effect.{Clock, IO, Ref}
import cats.implicits.toTraverseOps
import fetch.FileNameService
import org.typelevel.log4cats.Logger
import org.typelevel.log4cats.slf4j.Slf4jLogger
import parse.Aggregate
import parse.Aggregate.UserQuery
import java.time.{Instant, LocalDate, LocalDateTime, ZoneId}
trait DataServiceTrait {
def save(fileName: String, content: String): IO[String]
def readFile(fileName: String): IO[List[String]]
def getInRange(from: LocalDateTime, to: LocalDateTime): IO[List[String]]
def getDates: IO[List[LocalDate]]
def getDateFileNames(date: LocalDate): IO[List[String]]
def getDatesByMonths(monthList: List[LocalDate]): IO[List[LocalDate]]
}
object DataService {
def of(
fileService: FileService,
postgresService: PostgresService
): IO[DataService] = {
for {
log <- Slf4jLogger.create[IO]
// fileNameService = new FileNameService()
// fileNames <- fileNameService.generateLast24Hours
// contents <- fileNames.traverse(fileName => fileService.readFile(fileName)
// .map(content => (fileName, content)))
// state = contents.toMap
// stateRef <- Ref.of[IO, Map[String, List[String]]](state)
} yield new DataService(fileService, postgresService, log)
// } yield new DataService(fileService, postgresService, new FileNameService(), log)
// } yield new DataService(fileService, postgresService, new FileNameService(), log, stateRef)
// } yield new DataService(fileService, new FileNameService(), log, stateRef)
}
}
class DataService private(
fileService: FileService,
postgresService: PostgresService,
// fileNameService: FileNameService,
log: Logger[IO],
// private val state: Ref[IO, Map[String, List[String]]]
) extends DataServiceTrait {
// private def logState: IO[Unit] = {
// state.get.flatMap(currentState => log.info(s"State keys: ${currentState.keys.size}"))
// }
//
// private def filterState: IO[Unit] = {
// fileNameService.generateLast24Hours.flatMap { last24Hours =>
// state.update(st => st.filterKeys(last24Hours.contains).toMap)
// }
// }
def save(fileName: String, content: String): IO[String] = {
// TODO replace unsafeRunSync to redeemWith
// postgresService.save(fileName, content).unsafeRunSync()
// postgresService.save(fileName, content)
for {
result <- fileService.save(fileName, content)
_ <- postgresService.save(fileName, content)
} yield result
// TODO delete this
// fileService.save(fileName, content)
// fileService.save(fileName, content).redeemWith(
// error => IO.raiseError(error),
// savedFileName => {
// state.update(st => st.updated(savedFileName, content.split("\n").toList)) *>
// filterState *>
// logState.as(savedFileName)
// }
// ).onError(error => log.info(s"errr... $error"))
}
def readFile(fileName: String): IO[List[String]] = fileService.readFile(fileName)
def getDateTimeEntries(dateTime: LocalDateTime): IO[List[String]] = postgresService.getDateTimeEntries(dateTime)
def getInRange(from: LocalDateTime, to: LocalDateTime): IO[List[String]] = fileService.getInRange(from, to)
def query(userQuery: UserQuery): IO[Map[String, Option[Aggregate.AggregateValue]]] = postgresService.query(userQuery)
def getDates: IO[List[LocalDate]] = fileService.getDates
def getDatesByMonths(monthList: List[LocalDate]): IO[List[LocalDate]] = {
// fileService.getDatesByMonths(monthList)
postgresService.getDatesByMonths(monthList)
}
def getDateFileNames(date: LocalDate): IO[List[String]] = {
// fileService.getDateFileNames(date)
postgresService.getDateFileNames(date)
}
// TODO implement getting full data from state
// def getLast24Hours: IO[List[String]] = {
// state.get.map(_.keys.toList.sorted)
// }
}
-103
View File
@@ -1,103 +0,0 @@
package db
import cats.effect.{IO, Resource}
import cats.implicits.toTraverseOps
import org.typelevel.log4cats.Logger
import org.typelevel.log4cats.slf4j.Slf4jLogger
import java.io.File
import java.nio.file.{Files, Paths}
import java.time.{LocalDate, LocalDateTime}
import java.time.format.DateTimeFormatter
import java.util.concurrent.Executors
import scala.concurrent.ExecutionContext
import scala.io.Source
import scala.util.Try
object FileService {
def of: IO[FileService] = {
Slf4jLogger.create[IO].map(logger => new FileService(logger))
}
}
class FileService(log: Logger[IO]) extends DataServiceTrait {
private val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmm")
private val dataPath = "./data"
private val nonDuplicatedLines = 34 // takes only first 34 lines of data as rest after 'Zosēni' is duplicated
private def readFileNames(path: String): IO[List[String]] =
IO.blocking(new File(path).listFiles.toList.map(_.getName))
.handleError(_ => List.empty)
private def inRange(fileName: String, from: LocalDateTime, to: LocalDateTime): Boolean = {
def fileToDateTime(fileName: String): Option[LocalDateTime] = {
val dateString = fileName.split("\\.").head
Try(LocalDateTime.parse(dateString, dateFormatter)).toOption
}
val fileDateTime = fileToDateTime(fileName.stripSuffix (".csv"))
fileDateTime match {
case Some (date) => date.plusSeconds (1).isAfter (from) && date.minusSeconds (1).isBefore (to)
case None => false
}
}
def save(fileName: String, content: String): IO[String] = {
val path = Paths.get(s"$dataPath/$fileName")
IO(Files.writeString(path, content))
.attempt
.flatMap {
case Left(error) => log.error(s"Write file '$fileName' failed with error: ${error.getMessage}") *> IO.raiseError(error)
case Right(_) => log.info(s"write: $fileName").as(fileName)
}
}
def readFile(fileName: String): IO[List[String]] = {
val file = new File(dataPath, fileName)
val sourceResource = Resource.fromAutoCloseable(IO.blocking(Source.fromFile(file)))
sourceResource
.use(source => IO.blocking(source.getLines().take(nonDuplicatedLines).toList))
.handleError(_ => List.empty)
}
def getInRange(from: LocalDateTime, to: LocalDateTime): IO[List[String]] = {
for {
fileNames <- readFileNames(dataPath)
.map (_.filter (inRange (_, from, to)))
fileLines <- fileNames.traverse(readFile)
} yield fileLines.flatten
}
// dates in which we have saved data
def getDates: IO[List[LocalDate]] = {
val formatter = DateTimeFormatter.ofPattern("yyyyMMdd")
for {
fileNames <- readFileNames(dataPath)
datesStr <- IO(fileNames.map(_.take(8)).distinct) // take yyyyMMdd
dates <- datesStr.traverse { str =>
IO(LocalDate.parse(str, formatter)).option
}.map(_.flatten)
} yield dates.sorted
}
def getDatesByMonths(monthList: List[LocalDate]): IO[List[LocalDate]] = {
val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val monthFormatter = DateTimeFormatter.ofPattern("yyyyMM")
val monthStrList = monthList.map(_.format(monthFormatter))
for {
fileNames <- readFileNames(dataPath)
datesStr <- IO(fileNames.map(_.take(8)).distinct) // take yyyyMMdd
filteredDatesStr = datesStr.filter(date => monthStrList.contains(date.take(6)))
dates <- filteredDatesStr.traverse { str =>
IO(LocalDate.parse(str, dateFormatter)).option
}.map(_.flatten)
} yield dates.sorted
}
def getDateFileNames(date: LocalDate): IO[List[String]] = {
val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMdd")
val dateStr: String = date.format(formatter)
readFileNames(dataPath).map(_.filter(_.startsWith(dateStr)).sorted)
}
}
+1 -3
View File
@@ -22,7 +22,7 @@ object PostgresService {
}
}
class PostgresService(transactor: Transactor[IO], log: Logger[IO]) extends DataServiceTrait {
class PostgresService(transactor: Transactor[IO], log: Logger[IO]) {
private val rigaZone = ZoneId.of("Europe/Riga")
// in pgAdmin run: ```SET TIMEZONE = 'Europe/Riga';```
@@ -40,7 +40,6 @@ class PostgresService(transactor: Transactor[IO], log: Logger[IO]) extends DataS
def query(userQuery: UserQuery): IO[Map[String, Option[AggregateValue]]] = {
if (userQuery.field == "phenomena") { // this handles strings
// TODO query list and distinct values from phenomena
println("EMPTY RESULT!!!!!111")
IO(Map()) // empty result
} else if (List(
AggregateKey.Max,
@@ -145,7 +144,6 @@ class PostgresService(transactor: Transactor[IO], log: Logger[IO]) extends DataS
}
} else {
println("EMPTY RESULT!!!!!")
IO(Map()) // empty result
}
}