I'm trying to mimic a periodic token refresh. We have javascript code in our frontend that periodically checks if a token refresh needs to occur, and if so, issues a call to refresh the token. This is ran every couple minutes or so as long as anyone is using the application.
The typical user of our application will leave the app open without doing anything on it for time greater than the token lifetime. So I can't simply check and perform a token refresh on each call without adjusting the script to not mimic real life usage (because calls would need to occur more frequently).
Any ideas if, or how, this could be possible?
Okay, the best solution I could come up with was essentially to create my own "Pause" class, that breaks long pauses down into small pauses, and between each checks to see if the token needs refreshed. Looks roughly like this:
//new RefreshADToken().create() creates a ChainBuilder that refreshes the token if it's necessary
object PauseHelpers {
val tooBigOfPauseThreshold = 150 //300 seconds = 5 minutes, so anything over 150 is too big
def adPause(duration: Int): ChainBuilder = {
doIfOrElse(duration > tooBigOfPauseThreshold) {
val iterations = duration / tooBigOfPauseThreshold
repeat(iterations, "pause_counter") {
pause(tooBigOfPauseThreshold)
.exec(new RefreshADToken().create())
}.pause(duration % tooBigOfPauseThreshold).exec(new RefreshADToken().create())
} {
pause(duration).exec(new RefreshADToken().create())
}
}
}
//... then
import orhub.modules.actions._
class POC extends Simulation {
//some stuff
var scn = scenario("poc")
.feed(hospitalUsersFeeder)
.exec(session => {
session.set("env", environment)
})
.exec(new ADPause(120 * 60).create())
Related
Pretty positive I'm just totally overthinking this or approaching it from an illogical angle.
I'm separating my logic from my ui where button presses call a method located in the userModel which has a change notifier (getting passed into MyApp with a provider). I'm trying to implement firebase but have never called firebase directly from the ui (always just had the requests in the ui code, never used a model).
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:tuple/tuple.dart';
//TODO: firebase has been installed now I need to figure out how to implement it
// TODO: add firebase read and write
class UserModel with ChangeNotifier {
//index = session number
List session = [];
//create an instance of firebase (this might need to go higher in the tree)
var db = FirebaseFirestore.instance;
//TODO:
//convert incoming firebase to JSON
//convert outgoing json to firebase
//track session
// takes in current session data and adds the new chunk
// already recorded (new item in list but time, breaks etc. are adding from the last one)
// IF ADDING TO EXISTING, ALL PARAMETRS MUST BE SET
addSessionChunk(
{required String intention,
int workTime = 0,
String progress = "null",
int breakTime = 0}) {
session.add({
"intention": intention,
"workTime": workTime,
"progress": progress,
"breakTime": breakTime,
});
//firebase update?
}
//TODO: when returning to a previous intention, add to the numbers that were
//TODO: currently only works for 1 call per chunk (no going back to the same intention)
//get previous data from this intention for returning to a task (do
//these update functions updadate the LAST CHUNK in the session
updateChunkWorkTime({required int workTime}) {
//this later)
session.last["workTime"] = workTime;
}
//takes in inputed progress and updates the latest chunk with it
updateChunkProgress({required String progress}) {
session.last["progress"] = progress;
}
//takes inputed breaktime and updates the lastest chunk with it
updateChunkBreakTime({required int breakTime}) {
session.last["breakTime"] = breakTime;
}
//returns tuple of the total time spent working and breaking in the current session
calculateSessionTimeTotal() {
int totalWorkTime = 0;
int totalBreakTime = 0;
for (var chunk in session) {
totalWorkTime += chunk["workTime"] as int;
totalBreakTime += chunk["breakTime"] as int;
}
return Tuple2(totalWorkTime, totalBreakTime);
}
//firebase functions
pushDataUp() {
db.collection("sessions").doc().set({
"currentSession": session,
"total": calculateSessionTimeTotal().toString()
});
}
pullDataDown() {}
}
You can see at the bottom there I started to try and come up with a way to sync the local data state with firebase but am confused. Seems weird for the user to send their data up to firebase then back down into the model which is already holding that data?
Whats the best approach to local model and cloud database interaction? Any guidance in the right direction is greatly appreciated.
What seems weird to you, is actually a quite well defined patterns known as command query responsibility segregation, and is the basic pattern behind most modern UI frameworks. By separating the command (the writing of the data here) from the query (the reading of the data here) each remains simpler, and the total app becomes much easier to reason about.
With Firestore in Flutter, this usually translates into:
The user takes some action.
Your code writes to the database.
Your onSnapshot listener gets triggered with the updated data.
Your code updates the data model/state with the new data.
Which then renders the updated UI.
All of this happens pretty instantly, as Firebase actually handles it locally before even sending the data to the server and handles any exception that may occur during the synchronization with the server.
Scala application use case:
We have a Scala based that module reads the data from global cache (Redis) and save the same into local cache(Scaffeine). As we want this data to be refreshed asynchronously, we are using LoadingCache with refreshAfterWrite duration set to refresh window of 2.second.
Question:
We need to set different expiry time while setting values in local cache based on if key present in the redis (global cache) or not.
e.g.
If the key is not present in the global cache, we want to save the same key in local cache with default value and refresh window set to 5.minutes.
If key is present in the global cache, we want to store the same in local cache with actual value and refresh window set to 30.minute.
Sample code
object LocalCache extends App {
// data being stored in the cache
class DataObject(data: String) {
override def toString: String = {
"[ 'data': '" + this.data + "' ]"
}
}
// loader helper
private def loaderHelper(key: Int): Future[DataObject] = {
// this method will replace to read the data from Redis Cache
// for now, returns different values per key
if (key == 1) Future.successful(new DataObject("LOADER_HELPER_1"))
else if (key == 2) Future.successful(new DataObject("LOADER_HELPER_2"))
else Future.successful(new DataObject("LOADER_HELPER"))
}
// async loader
private def loader(key: Int): DataObject = {
Try {
Await.result(loaderHelper(key), 1.seconds)
} match {
case Success(result) =>
result
case Failure(exception: Exception) =>
val temp: DataObject = new DataObject("LOADER")
temp
}
}
// initCache
private def initCache(maximumSize: Int): LoadingCache[Int, DataObject] =
Scaffeine()
.recordStats()
.expireAfterWrite(2.second)
.maximumSize(maximumSize)
.build(loader)
// operations on the cache.
val cache: LoadingCache[Int, DataObject] = initCache(maximumSize = 500)
cache.put(1, new DataObject("foo"))
cache.put(2, new DataObject("hoo"))
println("sleeping for 3 sec\n")
Thread.sleep(3000)
println(cache.getIfPresent(1).toString)
println(cache.getIfPresent(2).toString)
println(cache.get(3).toString)
println("sleeping for 10 sec\n")
Thread.sleep(10000)
println("waking up from 10 sec sleep")
println(cache.get(1).toString)
println(cache.get(2).toString)
println(cache.get(3).toString)
println("\nCache Stats: "+ cache.stats())
}
I see lots of custom.policy that can be used to overwrite the expiryAfter policies (expiryAfterWrite/Update/Access) but nothing can be found for refreshAterWrite policies which refreshes the data asynchronously. Any help will be appreciable.
P.S.
I'm very newbie to work on Scala and also explore the Scaffeine.
Unfortunately variable refresh is not supported yet. There is an open issue to provide that feature.
At the moment expiration can be custom per entry, but automatic refresh is fixed. A manual refresh may be triggered by LoadingCache.refresh(key), if you want to manage it yourself. For example, you could periodically iterate over the entries (via the asMap() view) and refresh manually based on a custom criteria.
The AsyncLoadingCache could be useful instead of blocking on a future within your cache loader. The cache will return the in-flight future, won't make it expirable until the value materializes, and will remove it if it fails. Note that the synchronous() view is very useful for async caches to access more operations.
From testing, you might find Guava's fake ticker useful to simulate time.
Is there any way I can trigger a job from the controller (to not to wait for its completion) and display the message to the user that job will be running in the background?
I have one controller method which takes quite long time to run. So I want to make that run offline and display the message to the user that it will be running in the background.
I tried Action.async as shown below. But the processing of the Future object is still taking more time and getting timed out.
def submit(id: Int) = Action.async(parse.multipartFormData) { implicit request =>
val result = Future {
//process the data
}
result map {
res =>
Redirect(routes.testController.list()).flashing(("success", s"Job(s) will be ruuning in background."))
}
}
You can also return a result without waiting for the result of the future in a "fire and forget" way
def submit(id: Int) = Action(parse.multipartFormData) { implicit request =>
Future {
//process the data
}
Redirect(routes.testController.list()).flashing(("success", s"Job(s) will be running in background."))
}
The docs state:
By giving a Future[Result] instead of a normal Result, we are able to quickly generate the result without blocking. Play will then serve the result as soon as the promise is redeemed.
The web client will be blocked while waiting for the response, but nothing will be blocked on the server, and server resources can be used to serve other clients.
You can configure your client code to use ajax request and display a Waiting for data message for some part of the page without blocking the rest of the web page from loading.
I also tried the "Futures.timeout" option. It seems to work fine. But I'm not sure its correct way to do it or not.
result.withTimeout(20.seconds)(futures).map { res =>
Redirect(routes.testController.list()).flashing(("success", s"Job(s) will be updated in background."))
}.recover {
case e: scala.concurrent.TimeoutException =>
Redirect(routes.testController.list()).flashing(("success", s"Job(s) will be updated in background."))
}
I'm writing Selenium tests with ScalaTest's Selenium DSL and I'm running into timeouts I can't explain. To make matters more complicated, they only seem to happen some of the time.
The problem occurs whenever I access an Element after a page load or some Javascript rendering. It looks like this:
click on "editEmployee"
eventually {
textField(name("firstName")).value = "Steve"
}
My PatienceConfig is configured like this:
override implicit val patienceConfig: PatienceConfig =
PatienceConfig(timeout = Span(5, Seconds), interval = Span(50, Millis))
The test fails with the following error:
- should not display the old data after an employee was edited *** FAILED ***
The code passed to eventually never returned normally. Attempted 1 times over 10.023253653000001 seconds.
Last failure message: WebElement 'firstName' not found.. (EditOwnerTest.scala:24)
It makes sense that it doesn't succeed immediately, because the click causes some rendering, and the textfield may not be available right away. However, it shouldn't take 10 seconds to make an attempt to find it, right?
Also, I find it very interesting that the eventually block tried it only once, and that it took almost precisely 10 seconds. This smells like a timeout occurred somewhere, and it's not my PatienceConfig, because that was set to time out after 5 seconds.
With this workaround, it does work:
click on "editEmployee"
eventually {
find(name("firstName")).value // from ScalaTest's `OptionValues`
}
textField(name("firstName")).value = "Steve"
I did some digging in the ScalaTest source, and I've noticed that all calls that have this problem (it's not just textField), eventually call webElement at some point. The reason why the workaround works, is because it doesn't call webElement. webElement is defined like this:
def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = {
try {
driver.findElement(by)
}
catch {
case e: org.openqa.selenium.NoSuchElementException =>
// the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem.
val queryStringValue = queryString
throw new TestFailedException(
(_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."),
Some(e),
pos
)
}
}
I've copied that code into my project and played around with it, and it looks like constructing and/or throwing the exception is where most of the 10 seconds are spent.
(EDIT Clarification: I've actually seen the code actually spend its 10 seconds inside the catch block. The implicit wait is set to 0, and besides, if I remove the catch block everything simply works as expected.)
So my question is, what can I do to avoid this strange behaviour? I don't want to have to insert superfluous calls to find all the time, because it's easily forgotten, especially since, as I said, the error occurs only some of the time. (I haven't been able to determine when the behaviour occurs and when it doesn't.)
It is clear that the textField(name("firstName")).value = "Steve" ends up calling the WebElement as you have found out.
Since the issue in the op is happening where ever web elements are involved (which in turn implies that webdriver is involved), I think it is safe to assume that the issue is related to the implicit wait on the Web driver.
implicitlyWait(Span(0, Seconds))
The above should ideally fix the issue. Also, making implicit wait to be 0 is a bad practice. Any web page might have some loading issues. The page load is handled by Selenium outside its wait conditions. But slow element load (may be due to ajax calls) could result in failure. I usually keep 10 seconds as my standard implicit wait. For scenarios which require more wait, explicit waits can be used.
def implicitlyWait(timeout: Span)(implicit driver: WebDriver): Unit = {
driver.manage.timeouts.implicitlyWait(timeout.totalNanos, TimeUnit.NANOSECONDS)
}
Execution Flow:
name("firstName") ends up having value as Query {Val by = By.className("firstName") }.
def name(elementName: String): NameQuery = new NameQuery(elementName)
case class NameQuery(queryString: String) extends Query { val by = By.name(queryString) }
Query is fed to the textField method which calls the Query.webElement as below.
def textField(query: Query)(implicit driver: WebDriver, pos: source.Position): TextField = new TextField(query.webElement)(pos)
sealed trait Query extends Product with Serializable {
val by: By
val queryString: String
def webElement(implicit driver: WebDriver, pos: source.Position = implicitly[source.Position]): WebElement = {
try {
driver.findElement(by)
}
catch {
case e: org.openqa.selenium.NoSuchElementException =>
// the following is avoid the suite instance to be bound/dragged into the messageFun, which can cause serialization problem.
val queryStringValue = queryString
throw new TestFailedException(
(_: StackDepthException) => Some("WebElement '" + queryStringValue + "' not found."),
Some(e),
pos
)
}
}
}
I don't know ScalaTest's specifics, but such strange timeouts usually occur when you're mixing up implicit and explicit waits together.
driver.findElement uses implicit waits internally. And depending on specified explicit waits timeout, you may face with summing both together.
Ideally, implicit waits should be set to 0 to avoid such issues.
My app has a long running task (anywhere from 5 minutes to 2 hours) that I can start through an admin panel.
I need a good way to know whether the task is currently running or not, so I can display the status on the admin panel and to prevent the task from being started twice.
Currently my code looks like this (simplified):
object TaskMonitor extends Controller {
var isRunning = false
// Displays the task status on the admin panel
def status = Action {
Ok.chunked(running &> Comet(callback = "parent.running"))
}
// Check task status every 100 ms
lazy val running: Enumerator[String] = {
Enumerator.generateM {
Promise.timeout(Some(isRunning.toString), 100 milliseconds)
}
}
// start the task, but only if it's not already running
def startTask = Action {
if (!isRunning) {
isRunning = true
val f = scala.concurrent.Future { Task.start }
f onComplete {
case _ => isRunning = false
}
}
Ok
}
}
Obviously this is has all kinds of issues, mainly the fact that I have unsynchronized mutable state (isRunning variable) in my controller.
What would be the correct way to go about what I want to achieve ?
You're right, you have unsynchronized mutable state. Is it really a problem? I mean this is your admin right? How many concurrent 'startTask' are you gonna send?
The recommended way to handle this in Play! is to use an Akka actor - you don't need any extra dependency, Play! includes Akka already.
Create an actor to hold your isRunning value; in startTask you can send a message to the actor to start the task (the actor will check if the task is not already running). To send the current status of the task you can query the actor for the value of isRunning.
This will give you a protected mutable state. Your choice to decide if it's really worth the trouble.