mirror of
https://github.com/Eyre-S/Coeur-Morny-Cono.git
synced 2024-11-25 12:37:39 +08:00
add scaladoc, change Long to EpochMillis, scheduler tests
- fix wrong Telegram EpochSeconds to EpochMillis conv at OnCallMe
This commit is contained in:
parent
f0d4471646
commit
9f908aa88e
@ -8,6 +8,7 @@ import cc.sukazyo.cono.morny.bot.api.EventListenerManager
|
|||||||
import cc.sukazyo.cono.morny.bot.event.{MornyEventListeners, MornyOnInlineQuery, MornyOnTelegramCommand, MornyOnUpdateTimestampOffsetLock}
|
import cc.sukazyo.cono.morny.bot.event.{MornyEventListeners, MornyOnInlineQuery, MornyOnTelegramCommand, MornyOnUpdateTimestampOffsetLock}
|
||||||
import cc.sukazyo.cono.morny.bot.query.MornyQueries
|
import cc.sukazyo.cono.morny.bot.query.MornyQueries
|
||||||
import cc.sukazyo.cono.morny.util.schedule.Scheduler
|
import cc.sukazyo.cono.morny.util.schedule.Scheduler
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
||||||
import com.pengrad.telegrambot.TelegramBot
|
import com.pengrad.telegrambot.TelegramBot
|
||||||
import com.pengrad.telegrambot.request.GetMe
|
import com.pengrad.telegrambot.request.GetMe
|
||||||
|
|
||||||
@ -54,7 +55,7 @@ class MornyCoeur (using val config: MornyConfig) {
|
|||||||
*
|
*
|
||||||
* in milliseconds.
|
* in milliseconds.
|
||||||
*/
|
*/
|
||||||
val coeurStartTimestamp: Long = System.currentTimeMillis
|
val coeurStartTimestamp: EpochMillis = System.currentTimeMillis
|
||||||
|
|
||||||
/** [[TelegramBot]] account of this Morny */
|
/** [[TelegramBot]] account of this Morny */
|
||||||
val account: TelegramBot = __loginResult.account
|
val account: TelegramBot = __loginResult.account
|
||||||
|
@ -73,13 +73,14 @@ class OnCallMe (using coeur: MornyCoeur) extends EventListener {
|
|||||||
lastDinnerData.forwardFromMessageId
|
lastDinnerData.forwardFromMessageId
|
||||||
)
|
)
|
||||||
import cc.sukazyo.cono.morny.util.CommonFormat.{formatDate, formatDuration}
|
import cc.sukazyo.cono.morny.util.CommonFormat.{formatDate, formatDuration}
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.escapeHtml as h
|
import cc.sukazyo.cono.morny.util.tgapi.formatting.TelegramParseEscape.escapeHtml as h
|
||||||
def lastDinner_dateMillis: Long = lastDinnerData.forwardDate longValue;
|
def lastDinner_dateMillis: EpochMillis = EpochMillis fromEpochSeconds lastDinnerData.forwardDate
|
||||||
coeur.account exec SendMessage(
|
coeur.account exec SendMessage(
|
||||||
req.from.id,
|
req.from.id,
|
||||||
"<i>on</i> <code>%s [UTC+8]</code>\n- <code>%s</code> <i>before</i>".formatted(
|
"<i>on</i> <code>%s [UTC+8]</code>\n- <code>%s</code> <i>before</i>".formatted(
|
||||||
h(formatDate(lastDinner_dateMillis, 8)),
|
h(formatDate(lastDinner_dateMillis, 8)),
|
||||||
h(formatDuration(lastDinner_dateMillis))
|
h(formatDuration(System.currentTimeMillis - lastDinner_dateMillis))
|
||||||
)
|
)
|
||||||
).parseMode(ParseMode HTML).replyToMessageId(sendResp.message.messageId)
|
).parseMode(ParseMode HTML).replyToMessageId(sendResp.message.messageId)
|
||||||
isAllowed = true
|
isAllowed = true
|
||||||
|
@ -6,6 +6,7 @@ import cc.sukazyo.cono.morny.daemon.MedicationTimer.calcNextRoutineTimestamp
|
|||||||
import cc.sukazyo.cono.morny.util.schedule.RoutineTask
|
import cc.sukazyo.cono.morny.util.schedule.RoutineTask
|
||||||
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
|
import cc.sukazyo.cono.morny.util.tgapi.TelegramExtensions.Bot.exec
|
||||||
import cc.sukazyo.cono.morny.util.CommonFormat
|
import cc.sukazyo.cono.morny.util.CommonFormat
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
||||||
import com.pengrad.telegrambot.model.{Message, MessageEntity}
|
import com.pengrad.telegrambot.model.{Message, MessageEntity}
|
||||||
import com.pengrad.telegrambot.request.{EditMessageText, SendMessage}
|
import com.pengrad.telegrambot.request.{EditMessageText, SendMessage}
|
||||||
import com.pengrad.telegrambot.response.SendResponse
|
import com.pengrad.telegrambot.response.SendResponse
|
||||||
@ -30,15 +31,15 @@ class MedicationTimer (using coeur: MornyCoeur) {
|
|||||||
|
|
||||||
override def name: String = DAEMON_THREAD_NAME_DEF
|
override def name: String = DAEMON_THREAD_NAME_DEF
|
||||||
|
|
||||||
def calcNextSendTime: Long =
|
def calcNextSendTime: EpochMillis =
|
||||||
val next_time = calcNextRoutineTimestamp(System.currentTimeMillis, use_timeZone, notify_atHour)
|
val next_time = calcNextRoutineTimestamp(System.currentTimeMillis, use_timeZone, notify_atHour)
|
||||||
logger info s"medication timer will send next notify at ${CommonFormat.formatDate(next_time, use_timeZone.getTotalSeconds / 60 / 60)} with $use_timeZone [$next_time]"
|
logger info s"medication timer will send next notify at ${CommonFormat.formatDate(next_time, use_timeZone.getTotalSeconds / 60 / 60)} with $use_timeZone [$next_time]"
|
||||||
next_time
|
next_time
|
||||||
|
|
||||||
override def firstRoutineTimeMillis: Long =
|
override def firstRoutineTimeMillis: EpochMillis =
|
||||||
calcNextSendTime
|
calcNextSendTime
|
||||||
|
|
||||||
override def nextRoutineTimeMillis (previousRoutineScheduledTimeMillis: Long): Long | Null =
|
override def nextRoutineTimeMillis (previousRoutineScheduledTimeMillis: EpochMillis): EpochMillis | Null =
|
||||||
calcNextSendTime
|
calcNextSendTime
|
||||||
|
|
||||||
override def main: Unit = {
|
override def main: Unit = {
|
||||||
@ -85,7 +86,7 @@ class MedicationTimer (using coeur: MornyCoeur) {
|
|||||||
object MedicationTimer {
|
object MedicationTimer {
|
||||||
|
|
||||||
@throws[IllegalArgumentException]
|
@throws[IllegalArgumentException]
|
||||||
def calcNextRoutineTimestamp (baseTimeMillis: Long, zone: ZoneOffset, notifyAt: Set[Int]): Long = {
|
def calcNextRoutineTimestamp (baseTimeMillis: EpochMillis, zone: ZoneOffset, notifyAt: Set[Int]): EpochMillis = {
|
||||||
if (notifyAt isEmpty) throw new IllegalArgumentException("notify time is not set")
|
if (notifyAt isEmpty) throw new IllegalArgumentException("notify time is not set")
|
||||||
var time = LocalDateTime.ofEpochSecond(
|
var time = LocalDateTime.ofEpochSecond(
|
||||||
baseTimeMillis / 1000, ((baseTimeMillis % 1000) * 1000 * 1000) toInt,
|
baseTimeMillis / 1000, ((baseTimeMillis % 1000) * 1000 * 1000) toInt,
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package cc.sukazyo.cono.morny.data
|
package cc.sukazyo.cono.morny.data
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.{EpochDays, EpochMillis}
|
||||||
import com.pengrad.telegrambot.model.User
|
import com.pengrad.telegrambot.model.User
|
||||||
|
|
||||||
import scala.language.postfixOps
|
import scala.language.postfixOps
|
||||||
|
|
||||||
object MornyJrrp {
|
object MornyJrrp {
|
||||||
|
|
||||||
def jrrp_of_telegramUser (user: User, timestamp: Long): Double =
|
def jrrp_of_telegramUser (user: User, timestamp: EpochMillis): Double =
|
||||||
jrrp_v_xmomi(user.id, timestamp/(1000*60*60*24)) * 100.0
|
jrrp_v_xmomi(user.id, EpochDays fromEpochMillis timestamp) * 100.0
|
||||||
|
|
||||||
private def jrrp_v_xmomi (identifier: Long, dayStamp: Long): Double =
|
private def jrrp_v_xmomi (identifier: Long, dayStamp: EpochDays): Double =
|
||||||
import cc.sukazyo.cono.morny.util.CommonEncrypt.MD5
|
import cc.sukazyo.cono.morny.util.CommonEncrypt.MD5
|
||||||
import cc.sukazyo.cono.morny.util.ConvertByteHex.toHex
|
import cc.sukazyo.cono.morny.util.ConvertByteHex.toHex
|
||||||
java.lang.Long.parseLong(MD5(s"$identifier@$dayStamp").toHex.substring(0, 4), 16) / (0xffff toDouble)
|
java.lang.Long.parseLong(MD5(s"$identifier@$dayStamp").toHex.substring(0, 4), 16) / (0xffff toDouble)
|
||||||
|
@ -10,9 +10,6 @@ object EpochDateTime {
|
|||||||
* aka. Milliseconds since 00:00:00 UTC on Thursday, 1 January 1970.
|
* aka. Milliseconds since 00:00:00 UTC on Thursday, 1 January 1970.
|
||||||
*/
|
*/
|
||||||
type EpochMillis = Long
|
type EpochMillis = Long
|
||||||
/** Time duration/interval in milliseconds. */
|
|
||||||
type DurationMillis = Long
|
|
||||||
|
|
||||||
object EpochMillis:
|
object EpochMillis:
|
||||||
/** convert a localtime with timezone to epoch milliseconds
|
/** convert a localtime with timezone to epoch milliseconds
|
||||||
*
|
*
|
||||||
@ -31,5 +28,41 @@ object EpochDateTime {
|
|||||||
def apply (time_zone: (String, String)): EpochMillis =
|
def apply (time_zone: (String, String)): EpochMillis =
|
||||||
time_zone match
|
time_zone match
|
||||||
case (time, zone) => apply(time, zone)
|
case (time, zone) => apply(time, zone)
|
||||||
|
|
||||||
|
/** Convert from [[EpochSeconds]].
|
||||||
|
*
|
||||||
|
* Due to the missing accuracy, the converted EpochMillis will
|
||||||
|
* be always in 0ms aligned.
|
||||||
|
*/
|
||||||
|
def fromEpochSeconds (epochSeconds: EpochSeconds): EpochMillis =
|
||||||
|
epochSeconds.longValue * 1000L
|
||||||
|
|
||||||
|
/** The UNIX Epoch Time in seconds.
|
||||||
|
*
|
||||||
|
* aka. Seconds since 00:00:00 UTC on Thursday, 1 January 1970.
|
||||||
|
*
|
||||||
|
* Normally is the epochSeconds = (epochMillis / 1000)
|
||||||
|
*
|
||||||
|
* Notice that, currently, it stores using [[Int]] (also the implementation
|
||||||
|
* method of Telegram), which will only store times before 2038-01-19 03:14:07.
|
||||||
|
*/
|
||||||
|
type EpochSeconds = Int
|
||||||
|
|
||||||
|
/** The UNIX Epoch Time in day.
|
||||||
|
*
|
||||||
|
* aka. days since 00:00:00 UTC on Thursday, 1 January 1970.
|
||||||
|
*
|
||||||
|
* Normally is the epochDays = (epochMillis / 1000 / 60 / 60 / 24)
|
||||||
|
*
|
||||||
|
* Notice that, currently, it stores using [[Short]] (also the implementation
|
||||||
|
* method of Telegram), which will only store times before 2059-09-18.
|
||||||
|
*/
|
||||||
|
type EpochDays = Short
|
||||||
|
object EpochDays:
|
||||||
|
def fromEpochMillis (epochMillis: EpochMillis): EpochDays =
|
||||||
|
(epochMillis / (1000*60*60*24)).toShort
|
||||||
|
|
||||||
|
/** Time duration/interval in milliseconds. */
|
||||||
|
type DurationMillis = Long
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
package cc.sukazyo.cono.morny.util.schedule
|
package cc.sukazyo.cono.morny.util.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.{DurationMillis, EpochMillis}
|
||||||
|
|
||||||
trait DelayedTask (
|
trait DelayedTask (
|
||||||
val delayedMillis: Long
|
val delayedMillis: DurationMillis
|
||||||
) extends Task {
|
) extends Task {
|
||||||
|
|
||||||
override val scheduledTimeMillis: Long = System.currentTimeMillis + delayedMillis
|
override val scheduledTimeMillis: EpochMillis = System.currentTimeMillis + delayedMillis
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DelayedTask {
|
object DelayedTask {
|
||||||
|
|
||||||
def apply (_name: String, delayedMillis: Long, task: =>Unit): DelayedTask =
|
def apply (_name: String, delayedMillis: DurationMillis, task: =>Unit): DelayedTask =
|
||||||
new DelayedTask (delayedMillis):
|
new DelayedTask (delayedMillis):
|
||||||
override val name: String = _name
|
override val name: String = _name
|
||||||
override def main: Unit = task
|
override def main: Unit = task
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
package cc.sukazyo.cono.morny.util.schedule
|
package cc.sukazyo.cono.morny.util.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.{DurationMillis, EpochMillis}
|
||||||
|
|
||||||
trait IntervalTask extends RoutineTask {
|
trait IntervalTask extends RoutineTask {
|
||||||
|
|
||||||
def intervalMillis: Long
|
def intervalMillis: DurationMillis
|
||||||
|
|
||||||
override def firstRoutineTimeMillis: Long =
|
override def firstRoutineTimeMillis: EpochMillis =
|
||||||
System.currentTimeMillis() + intervalMillis
|
System.currentTimeMillis() + intervalMillis
|
||||||
|
|
||||||
override def nextRoutineTimeMillis (
|
override def nextRoutineTimeMillis (
|
||||||
previousScheduledRoutineTimeMillis: Long
|
previousScheduledRoutineTimeMillis: EpochMillis
|
||||||
): Long|Null =
|
): EpochMillis|Null =
|
||||||
previousScheduledRoutineTimeMillis + intervalMillis
|
previousScheduledRoutineTimeMillis + intervalMillis
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object IntervalTask {
|
object IntervalTask {
|
||||||
|
|
||||||
def apply (_name: String, _intervalMillis: Long, task: =>Unit): IntervalTask =
|
def apply (_name: String, _intervalMillis: DurationMillis, task: =>Unit): IntervalTask =
|
||||||
new IntervalTask:
|
new IntervalTask:
|
||||||
override def intervalMillis: Long = _intervalMillis
|
override def intervalMillis: DurationMillis = _intervalMillis
|
||||||
override def name: String = _name
|
override def name: String = _name
|
||||||
override def main: Unit = task
|
override def main: Unit = task
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package cc.sukazyo.cono.morny.util.schedule
|
package cc.sukazyo.cono.morny.util.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.{DurationMillis, EpochMillis}
|
||||||
|
|
||||||
trait IntervalWithTimesTask extends IntervalTask {
|
trait IntervalWithTimesTask extends IntervalTask {
|
||||||
|
|
||||||
def times: Int
|
def times: Int
|
||||||
private var currentExecutedTimes = 1
|
private var currentExecutedTimes = 1
|
||||||
|
|
||||||
override def nextRoutineTimeMillis (previousScheduledRoutineTimeMillis: Long): Long | Null =
|
override def nextRoutineTimeMillis (previousScheduledRoutineTimeMillis: EpochMillis): EpochMillis | Null =
|
||||||
if currentExecutedTimes >= times then
|
if currentExecutedTimes >= times then
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
@ -16,11 +18,11 @@ trait IntervalWithTimesTask extends IntervalTask {
|
|||||||
|
|
||||||
object IntervalWithTimesTask {
|
object IntervalWithTimesTask {
|
||||||
|
|
||||||
def apply (_name: String, _intervalMillis: Long, _times: Int, task: =>Unit): IntervalWithTimesTask =
|
def apply (_name: String, _intervalMillis: DurationMillis, _times: Int, task: =>Unit): IntervalWithTimesTask =
|
||||||
new IntervalWithTimesTask:
|
new IntervalWithTimesTask:
|
||||||
override def name: String = _name
|
override def name: String = _name
|
||||||
override def times: Int = _times
|
override def times: Int = _times
|
||||||
override def intervalMillis: Long = _intervalMillis
|
override def intervalMillis: DurationMillis = _intervalMillis
|
||||||
override def main: Unit = task
|
override def main: Unit = task
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,45 @@
|
|||||||
package cc.sukazyo.cono.morny.util.schedule
|
package cc.sukazyo.cono.morny.util.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
||||||
|
|
||||||
|
/** The task that can execute multiple times with custom routine function.
|
||||||
|
*
|
||||||
|
* When creating a Routine Task, the task's [[firstRoutineTimeMillis]] function
|
||||||
|
* will be called and the result value will be the first task scheduled time.
|
||||||
|
*
|
||||||
|
* After every execution complete and enter the post effect, the [[nextRoutineTimeMillis]]
|
||||||
|
* function will be called, then its value will be stored as the new task's
|
||||||
|
* scheduled time and re-scheduled by its scheduler.
|
||||||
|
*/
|
||||||
trait RoutineTask extends Task {
|
trait RoutineTask extends Task {
|
||||||
|
|
||||||
private[schedule] var currentScheduledTimeMillis: Long = firstRoutineTimeMillis
|
private[schedule] var currentScheduledTimeMillis: EpochMillis = firstRoutineTimeMillis
|
||||||
override def scheduledTimeMillis: Long = currentScheduledTimeMillis
|
|
||||||
|
|
||||||
def firstRoutineTimeMillis: Long
|
/** Next running time of this task.
|
||||||
|
*
|
||||||
|
* Should be auto generated from [[firstRoutineTimeMillis]] and
|
||||||
|
* [[nextRoutineTimeMillis]].
|
||||||
|
*/
|
||||||
|
override def scheduledTimeMillis: EpochMillis = currentScheduledTimeMillis
|
||||||
|
|
||||||
def nextRoutineTimeMillis (previousRoutineScheduledTimeMillis: Long): Long|Null
|
/** The task scheduled time at initial.
|
||||||
|
*
|
||||||
|
* In the default environment, this function will only be called once
|
||||||
|
* when the task object is just created.
|
||||||
|
*/
|
||||||
|
def firstRoutineTimeMillis: EpochMillis
|
||||||
|
|
||||||
|
/** The function to calculate the next scheduled time after previous task
|
||||||
|
* routine complete.
|
||||||
|
*
|
||||||
|
* This function will be called every time the task is done once, in the
|
||||||
|
* task runner thread and the post effect scope.
|
||||||
|
*
|
||||||
|
* @param previousRoutineScheduledTimeMillis The previous task routine's
|
||||||
|
* scheduled time.
|
||||||
|
* @return The next task routine's scheduled time, or [[null]] means end
|
||||||
|
* of the task.
|
||||||
|
*/
|
||||||
|
def nextRoutineTimeMillis (previousRoutineScheduledTimeMillis: EpochMillis): EpochMillis|Null
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package cc.sukazyo.cono.morny.util.schedule
|
package cc.sukazyo.cono.morny.util.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
||||||
|
|
||||||
import scala.annotation.targetName
|
import scala.annotation.targetName
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ class Scheduler {
|
|||||||
|
|
||||||
runtimeStatus = State.PREPARE_RUN
|
runtimeStatus = State.PREPARE_RUN
|
||||||
|
|
||||||
val nextMove: Task|Long|"None" = taskList.synchronized {
|
val nextMove: Task|EpochMillis|"None" = taskList.synchronized {
|
||||||
taskList.headOption match
|
taskList.headOption match
|
||||||
case Some(_readyToRun) if System.currentTimeMillis >= _readyToRun.scheduledTimeMillis =>
|
case Some(_readyToRun) if System.currentTimeMillis >= _readyToRun.scheduledTimeMillis =>
|
||||||
taskList -= _readyToRun
|
taskList -= _readyToRun
|
||||||
@ -107,7 +109,7 @@ class Scheduler {
|
|||||||
currentRunning match
|
currentRunning match
|
||||||
case routine: RoutineTask =>
|
case routine: RoutineTask =>
|
||||||
routine.nextRoutineTimeMillis(routine.currentScheduledTimeMillis) match
|
routine.nextRoutineTimeMillis(routine.currentScheduledTimeMillis) match
|
||||||
case next: Long =>
|
case next: EpochMillis =>
|
||||||
routine.currentScheduledTimeMillis = next
|
routine.currentScheduledTimeMillis = next
|
||||||
if (!currentRunning_isScheduledCancel) schedule(routine)
|
if (!currentRunning_isScheduledCancel) schedule(routine)
|
||||||
case _ =>
|
case _ =>
|
||||||
@ -117,7 +119,7 @@ class Scheduler {
|
|||||||
currentRunning = null
|
currentRunning = null
|
||||||
this setName runnerName
|
this setName runnerName
|
||||||
|
|
||||||
case needToWaitMillis: Long =>
|
case needToWaitMillis: EpochMillis =>
|
||||||
runtimeStatus = State.WAITING
|
runtimeStatus = State.WAITING
|
||||||
try Thread.sleep(needToWaitMillis)
|
try Thread.sleep(needToWaitMillis)
|
||||||
catch case _: InterruptedException => {}
|
catch case _: InterruptedException => {}
|
||||||
|
@ -55,3 +55,13 @@ trait Task extends Ordered[Task] {
|
|||||||
s"""${super.toString}{"$name": $scheduledTimeMillis}"""
|
s"""${super.toString}{"$name": $scheduledTimeMillis}"""
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object Task {
|
||||||
|
|
||||||
|
def apply (_name: String, _scheduledTime: EpochMillis, _main: =>Unit): Task =
|
||||||
|
new Task:
|
||||||
|
override def name: String = _name
|
||||||
|
override def scheduledTimeMillis: EpochMillis = _scheduledTime
|
||||||
|
override def main: Unit = _main
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -1,11 +1,55 @@
|
|||||||
package cc.sukazyo.cono.morny.test.utils
|
package cc.sukazyo.cono.morny.test.utils
|
||||||
|
|
||||||
import cc.sukazyo.cono.morny.test.MornyTests
|
import cc.sukazyo.cono.morny.test.MornyTests
|
||||||
import cc.sukazyo.cono.morny.util.EpochDateTime.EpochMillis
|
import cc.sukazyo.cono.morny.util.EpochDateTime.{EpochDays, EpochMillis, EpochSeconds}
|
||||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||||
|
|
||||||
class EpochDateTimeTest extends MornyTests with TableDrivenPropertyChecks {
|
class EpochDateTimeTest extends MornyTests with TableDrivenPropertyChecks {
|
||||||
|
|
||||||
|
"while converting to EpochMillis :" - {
|
||||||
|
|
||||||
|
"from EpochSeconds :" - {
|
||||||
|
|
||||||
|
val examples = Table[EpochSeconds, EpochMillis](
|
||||||
|
("EpochSeconds", "EpochMillis"),
|
||||||
|
(1699176068, 1699176068000L),
|
||||||
|
(1699176000, 1699176000000L),
|
||||||
|
(1, 1000L),
|
||||||
|
)
|
||||||
|
|
||||||
|
forAll(examples) { (epochSeconds, epochMillis) =>
|
||||||
|
s"EpochSeconds($epochSeconds) should be converted to EpochMillis($epochMillis)" in {
|
||||||
|
(EpochMillis fromEpochSeconds epochSeconds) shouldEqual epochMillis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"while converting to EpochDays :" - {
|
||||||
|
|
||||||
|
"from EpochMillis :" - {
|
||||||
|
|
||||||
|
val examples = Table(
|
||||||
|
("EpochMillis", "EpochDays"),
|
||||||
|
(0L, 0),
|
||||||
|
(1000L, 0),
|
||||||
|
(80000000L, 0),
|
||||||
|
(90000000L, 1),
|
||||||
|
(1699176549059L, 19666)
|
||||||
|
)
|
||||||
|
|
||||||
|
forAll(examples) { (epochMillis, epochDays) =>
|
||||||
|
s"EpochMillis($epochMillis) should be converted to EpochDays($epochDays)" in {
|
||||||
|
(EpochDays fromEpochMillis epochMillis) shouldEqual epochDays
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
"while converting date-time string to time-millis : " - {
|
"while converting date-time string to time-millis : " - {
|
||||||
|
|
||||||
"while using ISO-Offset-Date-Time : " - {
|
"while using ISO-Offset-Date-Time : " - {
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package cc.sukazyo.cono.morny.test.utils.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.test.MornyTests
|
||||||
|
import cc.sukazyo.cono.morny.util.schedule.{IntervalWithTimesTask, Scheduler}
|
||||||
|
import org.scalatest.tagobjects.Slow
|
||||||
|
|
||||||
|
class IntervalsTest extends MornyTests {
|
||||||
|
|
||||||
|
"IntervalWithTimesTest should work even scheduler is scheduled to stop" taggedAs Slow in {
|
||||||
|
val scheduler = Scheduler()
|
||||||
|
var times = 0
|
||||||
|
scheduler ++ IntervalWithTimesTask("intervals-10", 200, 10, {
|
||||||
|
times = times + 1
|
||||||
|
})
|
||||||
|
val startTime = System.currentTimeMillis()
|
||||||
|
scheduler.waitForStopAtAllDone()
|
||||||
|
val timeUsed = System.currentTimeMillis() - startTime
|
||||||
|
times shouldEqual 10
|
||||||
|
timeUsed should (be <= 2100L and be >= 1900L)
|
||||||
|
info(s"interval 200ms for 10 times used time ${timeUsed}ms")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package cc.sukazyo.cono.morny.test.utils.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.test.MornyTests
|
||||||
|
import cc.sukazyo.cono.morny.util.schedule.{DelayedTask, Scheduler, Task}
|
||||||
|
import org.scalatest.tagobjects.Slow
|
||||||
|
|
||||||
|
import scala.collection.mutable
|
||||||
|
|
||||||
|
class SchedulerTest extends MornyTests {
|
||||||
|
|
||||||
|
"While executing tasks using scheduler :" - {
|
||||||
|
|
||||||
|
"Task with scheduleTime smaller than current time should be executed immediately" in {
|
||||||
|
val scheduler = Scheduler()
|
||||||
|
var time = System.currentTimeMillis
|
||||||
|
scheduler ++ Task("task", 0, {
|
||||||
|
time = System.currentTimeMillis - time
|
||||||
|
})
|
||||||
|
scheduler.waitForStopAtAllDone()
|
||||||
|
time should be <= 10L
|
||||||
|
info(s"Immediately Task done with time $time")
|
||||||
|
}
|
||||||
|
|
||||||
|
"Task's running thread name should be task name" in {
|
||||||
|
val scheduler = Scheduler()
|
||||||
|
var executedThread: Option[String] = None
|
||||||
|
scheduler ++ Task("task", 0, {
|
||||||
|
executedThread = Some(Thread.currentThread.getName)
|
||||||
|
})
|
||||||
|
scheduler.waitForStopAtAllDone()
|
||||||
|
executedThread shouldEqual Some("task")
|
||||||
|
}
|
||||||
|
|
||||||
|
"Task's execution order should be ordered by task Ordering but not insert order" taggedAs Slow in {
|
||||||
|
val scheduler = Scheduler()
|
||||||
|
val result = mutable.ArrayBuffer.empty[String]
|
||||||
|
scheduler
|
||||||
|
++ DelayedTask("task-later", 400L, { result += Thread.currentThread.getName })
|
||||||
|
++ DelayedTask("task-very-late", 800L, { result += Thread.currentThread.getName })
|
||||||
|
++ DelayedTask("task-early", 100L, { result += Thread.currentThread.getName })
|
||||||
|
scheduler.waitForStopAtAllDone()
|
||||||
|
result.toArray shouldEqual Array("task-early", "task-later", "task-very-late")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package cc.sukazyo.cono.morny.test.utils.schedule
|
||||||
|
|
||||||
|
import cc.sukazyo.cono.morny.test.MornyTests
|
||||||
|
import cc.sukazyo.cono.morny.util.schedule.Task
|
||||||
|
import org.scalatest.tagobjects.Slow
|
||||||
|
|
||||||
|
class TaskBasicTest extends MornyTests {
|
||||||
|
|
||||||
|
"while comparing tasks :" - {
|
||||||
|
|
||||||
|
"tasks with different scheduleTime should be compared using scheduledTime" in {
|
||||||
|
Task("task-a", 21747013400912L, {}) should be > Task("task-b", 21747013400138L, {})
|
||||||
|
Task("task-a", 100L, {}) should be > Task("task-b", 99L, {})
|
||||||
|
Task("task-a", 100L, {}) should be < Task("task-b", 101, {})
|
||||||
|
Task("task-a", -19943L, {}) should be < Task("task-b", 0L, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
"task with the same scheduledTime should not be equal" in {
|
||||||
|
Task("same-task?", 0L, {}) should not equal Task("same-task?", 0L, {})
|
||||||
|
}
|
||||||
|
|
||||||
|
"tasks which is only the same object should be equal" in {
|
||||||
|
def createNewTask = Task("same-task?", 0L, {})
|
||||||
|
val task1 = createNewTask
|
||||||
|
val task2 = createNewTask
|
||||||
|
val task1_copy = task1
|
||||||
|
task1 shouldEqual task1_copy
|
||||||
|
task1 should not equal task2
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
"task can be sync executed by calling its main method." taggedAs Slow in {
|
||||||
|
|
||||||
|
Thread.currentThread setName "parent-thread"
|
||||||
|
val data = StringBuilder("")
|
||||||
|
val task = Task("some-task", 0L, {
|
||||||
|
Thread.sleep(100)
|
||||||
|
data ++= Thread.currentThread.getName ++= " // " ++= "task-complete"
|
||||||
|
})
|
||||||
|
task.main
|
||||||
|
data.toString shouldEqual "parent-thread // task-complete"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user