Skip to content

Commit

Permalink
#133: broken non-solution - result of pair programming session, idea …
Browse files Browse the repository at this point in the history
…is there but it does not compile
  • Loading branch information
lsulak committed Aug 15, 2024
1 parent 18b2106 commit be0544e
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 146 deletions.
7 changes: 4 additions & 3 deletions core/src/main/scala/za/co/absa/db/fadb/DBFunction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ package za.co.absa.db.fadb

import cats.MonadError
import cats.implicits.toFlatMapOps
import za.co.absa.db.fadb.exceptions.StatusException
import za.co.absa.db.fadb.status.aggregation.StatusAggregator
import za.co.absa.db.fadb.status.handling.StatusHandling
import za.co.absa.db.fadb.status.{FailedOrRows, FailedOrRow, Row}
import za.co.absa.db.fadb.status.{FailedOrRow, FailedOrRows, FunctionStatus, Row}

import scala.language.higherKinds

Expand Down Expand Up @@ -111,7 +112,7 @@ abstract class DBFunctionWithStatus[I, R, E <: DBEngine[F], F[_]](functionNameOv
* @return - A sequence of results from the database function.
*/
protected def multipleResults(values: I)(implicit me: MonadError[F, Throwable]): F[Seq[FailedOrRow[R]]] =
query(values).flatMap(q => dBEngine.fetchAllWithStatus(q))
query(values).flatMap((q: dBEngine.QueryWithStatusType[R]) => dBEngine.fetchAllWithStatus(q))

/**
* Executes the database function and returns a single result.
Expand Down Expand Up @@ -148,7 +149,7 @@ abstract class DBFunctionWithStatus[I, R, E <: DBEngine[F], F[_]](functionNameOv
protected def query(values: I)(implicit me: MonadError[F, Throwable]): F[dBEngine.QueryWithStatusType[R]]

// To be provided by an implementation of QueryStatusHandling
override def checkStatus[D](statusWithData: Row[D]): FailedOrRow[D]
override def checkStatus(functionStatus: FunctionStatus): Option[StatusException]
}

object DBFunction {
Expand Down
11 changes: 6 additions & 5 deletions core/src/main/scala/za/co/absa/db/fadb/Query.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

package za.co.absa.db.fadb

import za.co.absa.db.fadb.status.{FailedOrRow, Row}
import za.co.absa.db.fadb.exceptions.StatusException
import za.co.absa.db.fadb.status.{BlbyJmenoWithLayers, FailedOrRow, FunctionStatus, Row, StatusWithDataOptional}

/**
* The basis for all query types of [[DBEngine]] implementations
Expand All @@ -30,27 +31,27 @@ trait Query[R]
* @tparam D - the intermediate result type of the query (a row without status columns, i.e. data only)
* @tparam R - the final return type of the query (final version of result, depending on the needs, might be the same as D)
*/
trait QueryWithStatus[DS, D, R] {
abstract class QueryWithStatus[DS <: BlbyJmenoWithLayers[R], D, R](val processStatus: FunctionStatus => Option[StatusException]) extends Query[R] {

/**
* Processes the status of the query and returns the status with data
* @param initialResult - the initial result of the query
* @return data with status
*/
def processStatus(initialResult: DS): Row[D]
// def processStatus(initialResult: FunctionStatus): Option[StatusException]

/**
* Converts the status with data to either a status exception or the data
* @param statusWithData - the status with data
* @return either a status exception or the data
*/
def toStatusExceptionOrData(statusWithData: Row[D]): FailedOrRow[R]
// def toStatusExceptionOrData(statusWithData: StatusWithDataOptional[D]): FailedOrRow[R]

/**
* Returns the result of the query or a status exception
* @param initialResult - the initial result of the query
* @return the result of the query or a status exception
*/
def getResultOrException(initialResult: DS): FailedOrRow[R] =
toStatusExceptionOrData(processStatus(initialResult))
initialResult.toFailedOrRow(processStatus)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

package za.co.absa.db.fadb.status.handling

import za.co.absa.db.fadb.status.{FailedOrRow, Row}
import za.co.absa.db.fadb.exceptions.StatusException
import za.co.absa.db.fadb.status.{FailedOrRow, FunctionStatus, Row}

/**
* `StatusHandling` is a base trait that defines the interface for handling the status of a function invocation.
Expand All @@ -30,5 +31,5 @@ trait StatusHandling {
* @return Either a `StatusException` if the status code indicates an error, or the data (along with the status
* information so that it's retrievable) if the status code is successful.
*/
def checkStatus[D](statusWithData: Row[D]): FailedOrRow[D]
def checkStatus(functionStatus: FunctionStatus): Option[StatusException]
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package za.co.absa.db.fadb.status.handling.implementations

import za.co.absa.db.fadb.exceptions._
import za.co.absa.db.fadb.status.{FailedOrRow, Row}
import za.co.absa.db.fadb.status.{FailedOrRow, FunctionStatus, Row}
import za.co.absa.db.fadb.status.handling.StatusHandling

/**
Expand All @@ -29,16 +29,15 @@ trait StandardStatusHandling extends StatusHandling {
/**
* Checks the status of a function invocation.
*/
override def checkStatus[D](statusWithData: Row[D]): FailedOrRow[D] = {
val functionStatus = statusWithData.functionStatus
override def checkStatus(functionStatus: FunctionStatus): Option[StatusException] = {
functionStatus.statusCode / 10 match {
case 1 => Right(statusWithData)
case 2 => Left(ServerMisconfigurationException(functionStatus))
case 3 => Left(DataConflictException(functionStatus))
case 4 => Left(DataNotFoundException(functionStatus))
case 5 | 6 | 7 | 8 => Left(ErrorInDataException(functionStatus))
case 9 => Left(OtherStatusException(functionStatus))
case _ => Left(StatusOutOfRangeException(functionStatus))
case 1 => None
case 2 => Some(ServerMisconfigurationException(functionStatus))
case 3 => Some(DataConflictException(functionStatus))
case 4 => Some(DataNotFoundException(functionStatus))
case 5 | 6 | 7 | 8 => Some(ErrorInDataException(functionStatus))
case 9 => Some(OtherStatusException(functionStatus))
case _ => Some(StatusOutOfRangeException(functionStatus))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@

package za.co.absa.db.fadb.status.handling.implementations

import za.co.absa.db.fadb.exceptions.OtherStatusException
import za.co.absa.db.fadb.exceptions.{OtherStatusException, StatusException}
import za.co.absa.db.fadb.status.handling.StatusHandling
import za.co.absa.db.fadb.status.{FailedOrRow, Row}
import za.co.absa.db.fadb.status.{FailedOrRow, FunctionStatus, Row}

/**
* Trait represents user defined status handling
*/
trait UserDefinedStatusHandling extends StatusHandling {
def OKStatuses: Set[Integer]

override def checkStatus[D](statusWithData: Row[D]): FailedOrRow[D] =
if (OKStatuses.contains(statusWithData.functionStatus.statusCode)) {
Right(statusWithData)
override def checkStatus(functionStatus: FunctionStatus): Option[StatusException] =
if (OKStatuses.contains(functionStatus.statusCode)) {
None
} else {
Left(OtherStatusException(statusWithData.functionStatus))
Some(OtherStatusException(functionStatus))
}
}
19 changes: 19 additions & 0 deletions core/src/main/scala/za/co/absa/db/fadb/status/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package za.co.absa.db.fadb

import za.co.absa.db.fadb.exceptions.StatusException
import za.co.absa.db.fadb.status.FailedOrRow

package object status {

Expand All @@ -31,8 +32,26 @@ package object status {
* @param data the data of one row (barring the status fields)
* @tparam D the type of the data
*/

trait BlbyJmenoWithLayers[R] {
def toFailedOrRow(statusCheck: FunctionStatus => Option[StatusException]): FailedOrRow[R]
}

case class Row[D](functionStatus: FunctionStatus, data: D)

case class StatusWithDataOptional[R](status: Int, statusText: String, data: Option[R])
extends BlbyJmenoWithLayers[R]{

def toFailedOrRow(statusCheck: FunctionStatus => Option[StatusException]): FailedOrRow[R] = {
val functionStatus = FunctionStatus(status, statusText)
val left = statusCheck(functionStatus)
left match {
case Some(e) => Left(e)
case None => Right(Row(functionStatus, data.get))
}
}
}

/**
* This is a representation of a single row returned from a DB function with processed status information.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,98 +1,98 @@
/*
* Copyright 2022 ABSA Group Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package za.co.absa.db.fadb.status.handling.implementations

import org.scalatest.funsuite.AnyFunSuiteLike
import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
import za.co.absa.db.fadb.exceptions._
import za.co.absa.db.fadb.status.{FunctionStatus, Row}

class StandardStatusHandlingUnitTests extends AnyFunSuiteLike {

private val standardQueryStatusHandling = new StandardStatusHandling {}

test("checkStatus should return Right when status code is in the range 10-19") {
for (statusCode <- 10 to 19) {
val functionStatus = FunctionStatus(statusCode, "Success")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Right(statusWithData)
}
}

test("checkStatus should return Left with ServerMisconfigurationException when status code is in the range 20-29") {
for (statusCode <- 20 to 29) {
val functionStatus = FunctionStatus(statusCode, "Server Misconfiguration")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(ServerMisconfigurationException(functionStatus))
}
}

test("checkStatus should return Left with DataConflictException when status code is in the range 30-39") {
for (statusCode <- 30 to 39) {
val functionStatus = FunctionStatus(statusCode, "Data Conflict")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(DataConflictException(functionStatus))
}
}

test("checkStatus should return Left with DataNotFoundException when status code is in the range 40-49") {
for (statusCode <- 40 to 49) {
val functionStatus = FunctionStatus(statusCode, "Data Not Found")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(DataNotFoundException(functionStatus))
}
}

test("checkStatus should return Left with ErrorInDataException when status code is in the range 50-89") {
for (statusCode <- 50 to 89) {
val functionStatus = FunctionStatus(statusCode, "Error in Data")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(ErrorInDataException(functionStatus))
}
}

test("checkStatus should return Left with OtherStatusException when status code is in the range 90-99") {
for (statusCode <- 90 to 99) {
val functionStatus = FunctionStatus(statusCode, "Other Status")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(OtherStatusException(functionStatus))
}
}

test("checkStatus should return Left with StatusOutOfRangeException when status code is not in any known range") {
for (statusCode <- 0 to 9) {
val functionStatus = FunctionStatus(statusCode, "Out of range")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(StatusOutOfRangeException(functionStatus))
}

for (statusCode <- 100 to 110) {
val functionStatus = FunctionStatus(statusCode, "Out of range")
val statusWithData = Row(functionStatus, "Data")
val result = standardQueryStatusHandling.checkStatus(statusWithData)
result shouldBe Left(StatusOutOfRangeException(functionStatus))
}
}

}
///*
// * Copyright 2022 ABSA Group Limited
// *
// * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package za.co.absa.db.fadb.status.handling.implementations
//
//import org.scalatest.funsuite.AnyFunSuiteLike
//import org.scalatest.matchers.should.Matchers.convertToAnyShouldWrapper
//import za.co.absa.db.fadb.exceptions._
//import za.co.absa.db.fadb.status.{FunctionStatus, Row}
//
//class StandardStatusHandlingUnitTests extends AnyFunSuiteLike {
//
// private val standardQueryStatusHandling = new StandardStatusHandling {}
//
// test("checkStatus should return Right when status code is in the range 10-19") {
// for (statusCode <- 10 to 19) {
// val functionStatus = FunctionStatus(statusCode, "Success")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Right(statusWithData)
// }
// }
//
// test("checkStatus should return Left with ServerMisconfigurationException when status code is in the range 20-29") {
// for (statusCode <- 20 to 29) {
// val functionStatus = FunctionStatus(statusCode, "Server Misconfiguration")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(ServerMisconfigurationException(functionStatus))
// }
// }
//
// test("checkStatus should return Left with DataConflictException when status code is in the range 30-39") {
// for (statusCode <- 30 to 39) {
// val functionStatus = FunctionStatus(statusCode, "Data Conflict")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(DataConflictException(functionStatus))
// }
// }
//
// test("checkStatus should return Left with DataNotFoundException when status code is in the range 40-49") {
// for (statusCode <- 40 to 49) {
// val functionStatus = FunctionStatus(statusCode, "Data Not Found")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(DataNotFoundException(functionStatus))
// }
// }
//
// test("checkStatus should return Left with ErrorInDataException when status code is in the range 50-89") {
// for (statusCode <- 50 to 89) {
// val functionStatus = FunctionStatus(statusCode, "Error in Data")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(ErrorInDataException(functionStatus))
// }
// }
//
// test("checkStatus should return Left with OtherStatusException when status code is in the range 90-99") {
// for (statusCode <- 90 to 99) {
// val functionStatus = FunctionStatus(statusCode, "Other Status")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(OtherStatusException(functionStatus))
// }
// }
//
// test("checkStatus should return Left with StatusOutOfRangeException when status code is not in any known range") {
// for (statusCode <- 0 to 9) {
// val functionStatus = FunctionStatus(statusCode, "Out of range")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(StatusOutOfRangeException(functionStatus))
// }
//
// for (statusCode <- 100 to 110) {
// val functionStatus = FunctionStatus(statusCode, "Out of range")
// val statusWithData = Row(functionStatus, "Data")
// val result = standardQueryStatusHandling.checkStatus(statusWithData)
// result shouldBe Left(StatusOutOfRangeException(functionStatus))
// }
// }
//
//}
Loading

0 comments on commit be0544e

Please sign in to comment.