Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Put subcatalogs in IO #733

Merged
merged 1 commit into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions core/src/main/scala/latis/catalog/Catalog.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ trait Catalog { self =>
def datasets: Stream[IO, Dataset]

/** This catalog's subcatalogs. */
def catalogs: Map[Identifier, Catalog] = Map.empty
def catalogs: IO[Map[Identifier, Catalog]] = IO.pure(Map.empty)

/** Adds a single subcatalog to this catalog. */
def addCatalog(id: Identifier, catalog: Catalog): Catalog = new Catalog {
override val datasets: Stream[IO, Dataset] = self.datasets

override val catalogs: Map[Identifier, Catalog] =
self.catalogs + (id -> catalog)
override val catalogs: IO[Map[Identifier, Catalog]] =
self.catalogs.map(_ + (id -> catalog))
}

/**
Expand All @@ -51,17 +51,20 @@ trait Catalog { self =>
def filter(p: Dataset => Boolean): Catalog = new Catalog {
override val datasets: Stream[IO, Dataset] = self.datasets.filter(p)

override val catalogs: Map[Identifier, Catalog] = self.catalogs.map {
case (id, cat) => id -> cat.filter(p)
override val catalogs: IO[Map[Identifier, Catalog]] = self.catalogs.map {
_.map {
case (id, cat) => id -> cat.filter(p)
}
}
}

/** Returns a subcatalog given its name. */
def findCatalog(name: Identifier): Option[Catalog] =
def findCatalog(name: Identifier): IO[Option[Catalog]] =
splitId(name) match {
case (Nil, id) => catalogs.get(id)
case (Nil, id) => catalogs.map(_.get(id))
case (q :: qs, id) =>
catalogs.get(q).flatMap(_.findCatalog(concatId(qs, id)))
OptionT(catalogs.map(_.get(q)))
.flatMapF(_.findCatalog(concatId(qs, id))).value
}

/**
Expand All @@ -72,14 +75,15 @@ trait Catalog { self =>
case (Nil, id) =>
datasets.find(_.id.forall(_ == id)).compile.last
case (q :: qs, id) =>
catalogs.get(q).flatTraverse(_.findDataset(concatId(qs, id)))
OptionT(catalogs.map(_.get(q)))
.flatMapF(_.findDataset(concatId(qs, id))).value
}

/** Sets this catalog's subcatalogs. */
def withCatalogs(scs: (Identifier, Catalog)*): Catalog = new Catalog {
override val datasets: Stream[IO,Dataset] = self.datasets

override val catalogs: Map[Identifier, Catalog] = scs.toMap
override val catalogs: IO[Map[Identifier, Catalog]] = scs.toMap.pure[IO]
}

// Constructs a qualified ID.
Expand Down
9 changes: 6 additions & 3 deletions core/src/test/scala/latis/catalog/CatalogSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ class CatalogSuite extends CatsEffectSuite {
// that datasets in this list are unique.
private def listAll(c: Catalog): IO[List[Dataset]] = {
def go(c: Catalog): Stream[IO, Dataset] = {
c.datasets ++ c.catalogs.toList.foldMap { case (_, c) => go(c) }
c.datasets ++ Stream.eval(c.catalogs).flatMap(
sub => Stream.emits(sub.toList)
).flatMap { case (_, c) => go(c) }
}
go(c).compile.toList
}
Expand Down Expand Up @@ -75,8 +77,9 @@ class CatalogSuite extends CatsEffectSuite {
}

test("find catalog in a nested catalog") {
nested.findCatalog(id"b.c")
.fold(fail("Failed to find catalog"))(assertEquals(_, c2))
nested.findCatalog(id"b.c").map(
_.fold(fail("Failed to find catalog"))(assertEquals(_, c2))
)
}

test("find dataset in a nested catalog") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Dap2Service(catalog: Catalog, operationRegistry: OperationRegistry)
// Dataset path should not end with slash
if (path.endsWithSlash) NotFound(s"Resource not found: $path")
else datasetResponse(ds, ext, query)
case None => catalog.findCatalog(id) match {
case None => catalog.findCatalog(id).flatMap {
case Some(cat) => catalogResponse(cat, headers)
case None => NotFound(s"Resource not found: $path")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ object HtmlCatalogEncoder {

/** Provides a recursive HTML table representation of a Catalog's sub-catalogs */
private[dap2] def subcatalogTable(catalog: Catalog, prefix: String = ""): IO[Text.TypedTag[String]] = {
val catalogs = Stream.emits(catalog.catalogs.toList)
val catalogs = Stream.eval(catalog.catalogs).flatMap(sub => Stream.emits(sub.toList))
catalogs.evalMap { c =>
val id = c._1.asString
val cat = c._2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ object JsonCatalogEncoder {
/** Provides a JSON representation of a Catalog for a dap2 response. */
def encode(catalog: Catalog, id: Option[Identifier] = None): IO[Json] =
for {
cats <- catalog.catalogs.toList.traverse { case (id, cat) => encode(cat, Some(id)) }
subs <- catalog.catalogs
cats <- subs.toList.traverse { case (id, cat) => encode(cat, Some(id)) }
dss <- catalog.datasets.compile.toList.map(dss => dss.map(datasetToJson))
} yield {
val fields = List(
Expand Down
Loading