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

fix issue 488 #502

Merged
merged 1 commit into from
May 24, 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
4 changes: 4 additions & 0 deletions core/src/main/scala/besom/internal/Resource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ sealed trait Resource:
case _: CustomResource => true
case _ => false

// this method can lead to deadlocks as it waits for URN to be resolved, use carefully
// resources can be visually compared by references using toString() if URN is not strictly required
private[internal] def asString: Result[Option[String]] = urn.getValue.map(_.map(v => s"${this.getClass.getSimpleName}($v)"))

trait CustomResource extends Resource:
Expand All @@ -45,6 +47,8 @@ trait ComponentResource(using
*/
override def urn: Output[URN] = base.urn

private[besom] def componentBase: ComponentBase = base

trait ProviderResource extends CustomResource:
private[internal] def registrationId: Result[String] =
for
Expand Down
6 changes: 5 additions & 1 deletion core/src/main/scala/besom/internal/ResourceState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,25 @@ case class CommonResourceState(
typ: ResourceType,
// transformations: List[ResourceTransformation],
keepDependency: Boolean
)
):
override def toString(): String = "CommonResourceState"

case class CustomResourceState(
common: CommonResourceState,
id: Output[ResourceId]
) extends ResourceState:
export common.*
override def toString(): String = "CustomResourceState"

case class ProviderResourceState(
custom: CustomResourceState,
pkg: String
) extends ResourceState:
export custom.*
override def toString(): String = "ProviderResourceState"

case class ComponentResourceState(
common: CommonResourceState
) extends ResourceState:
export common.*
override def toString(): String = "ComponentResourceState"
73 changes: 44 additions & 29 deletions core/src/main/scala/besom/internal/resources.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
package besom.internal

class ResourceStateMismatchException(msg: String) extends Exception(msg)
object ResourceStateMismatchException:
def fail(r: Resource, state: ResourceState, expected: String)(using dbg: Debug): Result[Nothing] =
(for
rstr <- r.asString
msg = s"state for resource $r / ${rstr.getOrElse("???")} is $state, expected $expected, caller: $dbg"
yield new ResourceStateMismatchException(msg)).flatMap(e => Result.fail(e))

class ResourceStateMissingException(msg: String) extends Exception(msg)
object ResourceStateMissingException:
inline private def nl = System.lineSeparator
def fail(r: Resource, rs: Map[Resource, ResourceState])(using dbg: Debug): Result[Nothing] =
(for
rstr <- r.asString
msg = s"state for resource $r / ${rstr.getOrElse("???")} not found$nl - caller: $dbg$nl - state available for resources:$nl${rs.keys
.mkString(" * ", nl + " * ", "")}"
yield new ResourceStateMissingException(msg)).flatMap(e => Result.fail(e))

class Resources private (private val resources: Ref[Map[Resource, ResourceState]]):
def add(resource: ProviderResource, state: ProviderResourceState): Result[Unit] =
resources.update(_ + (resource -> state))
Expand All @@ -25,56 +43,53 @@ class Resources private (private val resources: Ref[Map[Resource, ResourceState]
case _ =>
resource.asString.flatMap(s => Result.fail(Exception(s"resource ${s} and state ${state} don't match")))

def getStateFor(resource: ProviderResource): Result[ProviderResourceState] =
resources.get.flatMap {
_.get(resource) match
def getStateFor(resource: ProviderResource)(using Debug): Result[ProviderResourceState] =
resources.get.flatMap { rs =>
rs.get(resource) match
case Some(state) =>
state match
case _: CustomResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for ProviderResource ${s} is a CustomResourceState!")))
case prs: ProviderResourceState => Result.pure(prs)
case _: ComponentResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for ProviderResource ${s} is a ComponentResourceState!")))
case _ => ResourceStateMismatchException.fail(resource, state, "ProviderResourceState")

case None =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for resource ${s} not found")))
ResourceStateMissingException.fail(resource, rs)
}

def getStateFor(resource: CustomResource): Result[CustomResourceState] =
resources.get.flatMap {
_.get(resource) match
def getStateFor(resource: CustomResource)(using Debug): Result[CustomResourceState] =
resources.get.flatMap { rs =>
rs.get(resource) match
case Some(state) =>
state match
case crs: CustomResourceState => Result.pure(crs)
case _: ProviderResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for CustomResource ${s} is a ProviderResourceState!")))
case _: ComponentResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for CustomResource ${s} is a ComponentResourceState!")))
case _ => ResourceStateMismatchException.fail(resource, state, "CustomResourceState")

case None =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for resource ${s} not found")))
ResourceStateMissingException.fail(resource, rs)
}

def getStateFor(resource: ComponentResource): Result[ComponentResourceState] =
resources.get.flatMap {
_.get(resource) match
def getStateFor(resource: ComponentResource)(using Debug): Result[ComponentResourceState] =
resources.get.flatMap { rs =>
rs.get(resource.componentBase) match
case Some(state) =>
state match
case _: CustomResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for ComponentResource ${s} is a CustomResourceState!")))
case _: ProviderResourceState =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for ComponentResource ${s} is a ProviderResourceState!")))
case comprs: ComponentResourceState => Result.pure(comprs)
case _ => ResourceStateMismatchException.fail(resource, state, "ComponentResourceState")

case None =>
resource.asString.flatMap(s => Result.fail(Exception(s"state for resource ${s} not found")))
ResourceStateMissingException.fail(resource, rs)
}

def getStateFor(resource: Resource): Result[ResourceState] =
resources.get.flatMap {
_.get(resource) match
case Some(state) => Result.pure(state)
case None => resource.asString.flatMap(s => Result.fail(Exception(s"state for resource ${s} not found")))
def getStateFor(resource: Resource)(using dbg: Debug): Result[ResourceState] =
resources.get.flatMap { rs =>
resource match
case compr: ComponentResource =>
rs.get(compr.componentBase) match
case Some(state) => Result.pure(state)
case None => ResourceStateMissingException.fail(resource, rs)
case _ =>
rs.get(resource) match
case Some(state) => Result.pure(state)
case None => ResourceStateMissingException.fail(resource, rs)
}

def updateStateFor(resource: Resource)(f: ResourceState => ResourceState): Result[Unit] =
Expand Down
Loading