Skip to content

Commit

Permalink
Merge pull request #2248 from constantine2nd/develop
Browse files Browse the repository at this point in the history
Metric; Timeout
  • Loading branch information
simonredfern authored Aug 21, 2023
2 parents 4a5e61e + 22b0c33 commit b9d6194
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 12 deletions.
6 changes: 3 additions & 3 deletions obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ import org.apache.commons.lang3.StringUtils
import java.security.AccessControlException
import java.util.regex.Pattern

import code.api.util.FutureUtil.EndpointTimeout
import code.api.util.FutureUtil.{EndpointContext, EndpointTimeout}
import code.etag.MappedETag
import code.users.Users
import net.liftweb.mapper.By
Expand Down Expand Up @@ -2956,7 +2956,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
* @tparam T
* @return
*/
implicit def scalaFutureToBoxedJsonResponse[T](scf: OBPReturnType[T])(implicit t: EndpointTimeout, m: Manifest[T]): Box[JsonResponse] = {
implicit def scalaFutureToBoxedJsonResponse[T](scf: OBPReturnType[T])(implicit t: EndpointTimeout, context: EndpointContext, m: Manifest[T]): Box[JsonResponse] = {
futureToBoxedResponse(scalaFutureToLaFuture(FutureUtil.futureWithTimeout(scf)))
}

Expand Down Expand Up @@ -3182,7 +3182,7 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
def authenticatedAccess(cc: CallContext, emptyUserErrorMsg: String = UserNotLoggedIn): OBPReturnType[Box[User]] = {
anonymousAccess(cc) map{
x => (
fullBoxOrException(x._1 ~> APIFailureNewStyle(emptyUserErrorMsg, 400, Some(cc.toLight))),
fullBoxOrException(x._1 ~> APIFailureNewStyle(emptyUserErrorMsg, 401, Some(cc.toLight))),
x._2
)
} map {
Expand Down
17 changes: 14 additions & 3 deletions obp-api/src/main/scala/code/api/util/FutureUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package code.api.util
import java.util.concurrent.TimeoutException
import java.util.{Timer, TimerTask}

import code.api.Constant
import code.api.{APIFailureNewStyle, Constant}
import net.liftweb.json.{Extraction, JsonAST}

import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.language.postfixOps
Expand All @@ -18,8 +19,11 @@ object FutureUtil {
val timer: Timer = new Timer(true)

case class EndpointTimeout(inMillis: Long)
case class EndpointContext(context: Option[CallContext])

implicit val defaultTimeout: EndpointTimeout = EndpointTimeout(Constant.longEndpointTimeoutInMillis)
implicit val callContext = EndpointContext(context = None)
implicit val formats = CustomJsonFormats.formats

/**
* Returns the result of the provided future within the given time or a timeout exception, whichever is first
Expand All @@ -29,7 +33,7 @@ object FutureUtil {
* @param timeout Time before we return a Timeout exception instead of future's outcome
* @return Future[T]
*/
def futureWithTimeout[T](future : Future[T])(implicit timeout : EndpointTimeout, ec: ExecutionContext): Future[T] = {
def futureWithTimeout[T](future : Future[T])(implicit timeout : EndpointTimeout, cc: EndpointContext, ec: ExecutionContext): Future[T] = {

// Promise will be fulfilled with either the callers Future or the timer task if it times out
var p = Promise[T]
Expand All @@ -38,7 +42,14 @@ object FutureUtil {

val timerTask = new TimerTask() {
def run() : Unit = {
p.tryFailure(new TimeoutException(ErrorMessages.requestTimeout))
p.tryFailure {
val error: String = JsonAST.compactRender(
Extraction.decompose(
APIFailureNewStyle(failMsg = ErrorMessages.requestTimeout, failCode = 408, cc.context.map(_.toLight))
)
)
new TimeoutException(error)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ object Migration extends MdcLoggable {
alterUserAttributeNameLength()
alterMappedCustomerAttribute(startedBeforeSchemifier)
dropMappedBadLoginAttemptIndex()
alterMetricColumnUrlLength()
}

private def dummyScript(): Boolean = {
Expand Down Expand Up @@ -416,6 +417,13 @@ object Migration extends MdcLoggable {
}
}

private def alterMetricColumnUrlLength(): Boolean = {
val name = nameOf(alterMetricColumnUrlLength)
runOnce(name) {
MigrationOfMetricTable.alterColumnCorrelationidLength(name)
}
}

private def dropConsentAuthContextDropIndex(): Boolean = {
val name = nameOf(dropConsentAuthContextDropIndex)
runOnce(name) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package code.api.util.migration

import java.time.format.DateTimeFormatter
import java.time.{ZoneId, ZonedDateTime}

import code.api.util.APIUtil
import code.api.util.migration.Migration.{DbFunction, saveLog}
import code.metrics.MappedMetric
import net.liftweb.common.Full
import net.liftweb.mapper.{DB, Schemifier}
import net.liftweb.util.DefaultConnectionIdentifier

object MigrationOfMetricTable {

val oneDayAgo = ZonedDateTime.now(ZoneId.of("UTC")).minusDays(1)
val oneYearInFuture = ZonedDateTime.now(ZoneId.of("UTC")).plusYears(1)
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm'Z'")

def alterColumnCorrelationidLength(name: String): Boolean = {
DbFunction.tableExists(MappedMetric, (DB.use(DefaultConnectionIdentifier){ conn => conn}))
match {
case true =>
val startDate = System.currentTimeMillis()
val commitId: String = APIUtil.gitCommit
var isSuccessful = false

val executedSql =
DbFunction.maybeWrite(true, Schemifier.infoF _, DB.use(DefaultConnectionIdentifier){ conn => conn}) {
APIUtil.getPropsValue("db.driver") match {
case Full(value) if value.contains("com.microsoft.sqlserver.jdbc.SQLServerDriver") =>
() =>
"""
|ALTER TABLE metric ALTER COLUMN correlationid varchar(256);
|""".stripMargin
case _ =>
() =>
"""
|ALTER TABLE metric ALTER COLUMN correlationid TYPE character varying(256);
|""".stripMargin
}
}

val endDate = System.currentTimeMillis()
val comment: String =
s"""Executed SQL:
|$executedSql
|""".stripMargin
isSuccessful = true
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
isSuccessful

case false =>
val startDate = System.currentTimeMillis()
val commitId: String = APIUtil.gitCommit
val isSuccessful = false
val endDate = System.currentTimeMillis()
val comment: String =
s"""${MappedMetric._dbTableNameLC} table does not exist""".stripMargin
saveLog(name, commitId, isSuccessful, startDate, endDate, comment)
isSuccessful
}
}
}
12 changes: 7 additions & 5 deletions obp-api/src/main/scala/code/metrics/MappedMetrics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import java.util.Date
import java.util.UUID.randomUUID

import code.api.cache.Caching
import code.api.util.APIUtil.generateUUID
import code.api.util._
import code.model.MappedConsumersProvider
import code.util.Helper.MdcLoggable
Expand Down Expand Up @@ -90,9 +91,9 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
private def falseOrTrue(condition: Boolean): String = if (condition) s"0=1" else s"1=1"

private def sqlFriendly(value : Option[String]): String = {
value.isDefined match {
case true => s"'$value'"
case false => "null"
value match {
case Some(value) => s"'$value'"
case None => "null"

}
}
Expand Down Expand Up @@ -218,7 +219,7 @@ object MappedMetrics extends APIMetrics with MdcLoggable{
else
s""

s"${params.head})"+ sqlSingleLine + s" and url ${isLikeQuery} LIKE ('${params.last}''"
s"'${params.head}')"+ sqlSingleLine + s" and url ${isLikeQuery} LIKE ('${params.last}'"
}
}

Expand Down Expand Up @@ -531,8 +532,9 @@ class MappedMetric extends APIMetric with LongKeyedMapper[MappedMetric] with IdP
//(GET, POST etc.) --S.request.get.requestType
object verb extends MappedString(this, 16)
object httpCode extends MappedInt(this)
object correlationId extends MappedUUID(this){
object correlationId extends MappedString(this, 256) {
override def dbNotNull_? = true
override def defaultValue = generateUUID()
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ object MetricsArchiveScheduler extends MdcLoggable {
interval = Duration(intervalInSeconds, TimeUnit.SECONDS),
runnable = new Runnable {
def run(): Unit = {
logger.info("Hello from MetricsArchiveScheduler.start.run")
logger.info("Starting MetricsArchiveScheduler.start.run")
conditionalDeleteMetricsRow()
deleteOutdatedRowsFromMetricsArchive()
logger.info("End of MetricsArchiveScheduler.start.run")
}
}
)
logger.info("Bye from MetricsArchiveScheduler.start")
}

def deleteOutdatedRowsFromMetricsArchive() = {
Expand Down Expand Up @@ -80,6 +82,7 @@ object MetricsArchiveScheduler extends MdcLoggable {
maybeDeletedRows.filter(_._1 == false).map { i =>
logger.warn(s"Row with primary key ${i._2} of the table Metric is not successfully copied.")
}
logger.info("Bye from MetricsArchiveScheduler.conditionalDeleteMetricsRow")
}

private def copyRowToMetricsArchive(i: APIMetric): Unit = {
Expand Down

0 comments on commit b9d6194

Please sign in to comment.