Git Product home page Git Product logo

fs2-cron's Introduction

fs2-cron

GitHub Workflow Status codecov Join the chat at https://gitter.im/fthomas/fs2-cron Scaladex Scaladoc

fs2-cron is a microlibrary that provides FS2 streams based on Cron4s cron expressions or Calev calendar events.

It is provided for Scala 2.12, 2.13 and fs2-cron-calev also for Scala 3.

Examples

import cats.effect.IO
import cats.effect.unsafe.implicits.global
import fs2.Stream
import java.time.LocalTime

val printTime = Stream.eval(IO(println(LocalTime.now)))

Using Cron4s library

Requires the fs2-cron-cron4s module:

import cron4s.Cron
import eu.timepit.fs2cron.cron4s.Cron4sScheduler

val cronScheduler = Cron4sScheduler.systemDefault[IO]
// cronScheduler: eu.timepit.fs2cron.Scheduler[IO, cron4s.expr.CronExpr] = eu.timepit.fs2cron.cron4s.Cron4sScheduler$$anon$1@3b612fa5

val evenSeconds = Cron.unsafeParse("*/2 * * ? * *")
// evenSeconds: cron4s.package.CronExpr = CronExpr(
//   seconds = */2,
//   minutes = *,
//   hours = *,
//   daysOfMonth = ?,
//   months = *,
//   daysOfWeek = *
// )

val scheduled = cronScheduler.awakeEvery(evenSeconds) >> printTime
// scheduled: Stream[[x]IO[x], Unit] = Stream(..)

scheduled.take(3).compile.drain.unsafeRunSync()
// 22:34:46.145109392
// 22:34:48.001058522
// 22:34:50.001971813
val everyFiveSeconds = Cron.unsafeParse("*/5 * * ? * *")
// everyFiveSeconds: cron4s.package.CronExpr = CronExpr(
//   seconds = */5,
//   minutes = *,
//   hours = *,
//   daysOfMonth = ?,
//   months = *,
//   daysOfWeek = *
// )

val scheduledTasks = cronScheduler.schedule(List(
  evenSeconds      -> Stream.eval(IO(println(LocalTime.now.toString + " task 1"))),
  everyFiveSeconds -> Stream.eval(IO(println(LocalTime.now.toString + " task 2")))
))
// scheduledTasks: Stream[IO, Unit] = Stream(..)

scheduledTasks.take(9).compile.drain.unsafeRunSync()
// 22:34:52.001721651 task 1
// 22:34:54.001702294 task 1
// 22:34:55.002032079 task 2
// 22:34:56.000919733 task 1
// 22:34:58.000939089 task 1
// 22:35:00.001158852 task 1
// 22:35:00.001743567 task 2
// 22:35:02.001037743 task 1
// 22:35:04.001006980 task 1

Cancelling the scheduled task

Using Stream#interruptWhen(haltWhenTrue)

import cats.effect._
import cron4s.Cron
import eu.timepit.fs2cron.cron4s.Cron4sScheduler
import fs2.Stream
import fs2.concurrent.SignallingRef

import java.time.LocalTime
import scala.concurrent.duration._

object TestApp extends IOApp.Simple {
  val printTime = Stream.eval(IO(println(LocalTime.now)))

  override def run: IO[Unit] = {
    val cronScheduler = Cron4sScheduler.systemDefault[IO]
    val evenSeconds = Cron.unsafeParse("*/2 * * ? * *")
    val scheduled = cronScheduler.awakeEvery(evenSeconds) >> printTime
    val cancel = SignallingRef[IO, Boolean](false)

    for {
      c <- cancel
      s <- scheduled.interruptWhen(c).repeat.compile.drain.start
      //prints about 5 times before stop
      _ <- Temporal[IO].sleep(10.seconds) >> c.set(true)
    } yield s
  }
}

Using Calev library

Requires the fs2-cron-calev module:

import com.github.eikek.calev.CalEvent
import eu.timepit.fs2cron.calev.CalevScheduler

val calevScheduler = CalevScheduler.systemDefault[IO]
// calevScheduler: eu.timepit.fs2cron.Scheduler[IO, CalEvent] = eu.timepit.fs2cron.calev.CalevScheduler$$anon$1@5b72ab85
val oddSeconds = CalEvent.unsafe("*-*-* *:*:1/2")
// oddSeconds: CalEvent = CalEvent(
//   weekday = All,
//   date = DateEvent(year = All, month = All, day = All),
//   time = TimeEvent(
//     hour = All,
//     minute = All,
//     seconds = List(values = Vector(Single(value = 1, rep = Some(value = 2))))
//   ),
//   zone = None
// )

val calevScheduled = calevScheduler.awakeEvery(oddSeconds) >> printTime
// calevScheduled: Stream[[x]IO[x], Unit] = Stream(..)
calevScheduled.take(3).compile.drain.unsafeRunSync()
// 22:35:05.005121709
// 22:35:07.000442205
// 22:35:09.000989961
val everyFourSeconds = CalEvent.unsafe("*-*-* *:*:0/4")
// everyFourSeconds: CalEvent = CalEvent(
//   weekday = All,
//   date = DateEvent(year = All, month = All, day = All),
//   time = TimeEvent(
//     hour = All,
//     minute = All,
//     seconds = List(values = Vector(Single(value = 0, rep = Some(value = 4))))
//   ),
//   zone = None
// )

val calevScheduledTasks = calevScheduler.schedule(List(
  oddSeconds      -> Stream.eval(IO(println(LocalTime.now.toString + " task 1"))),
  everyFourSeconds -> Stream.eval(IO(println(LocalTime.now.toString + " task 2")))
))
// calevScheduledTasks: Stream[IO, Unit] = Stream(..)

calevScheduledTasks.take(9).compile.drain.unsafeRunSync()
// 22:35:11.000475346 task 1
// 22:35:12.000865309 task 2
// 22:35:13.000723319 task 1
// 22:35:15.001042916 task 1
// 22:35:16.000423061 task 2
// 22:35:17.000806045 task 1
// 22:35:19.000158236 task 1
// 22:35:20.000879932 task 2
// 22:35:21.000786710 task 1

Using fs2-cron

The latest version of the library is available for Scala 2.12 and 2.13.

If you're using sbt, add the following to your build:

libraryDependencies ++= Seq(
  "eu.timepit" %% "fs2-cron-cron4s" % "0.9.0" //and/or
  "eu.timepit" %% "fs2-cron-calev" % "0.9.0"
)

License

fs2-cron is licensed under the Apache License, Version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 and also in the LICENSE file.

fs2-cron's People

Contributors

eikek avatar fthomas avatar gatorcse avatar gitter-badger avatar kubukoz avatar kwark avatar lucafrancesc avatar mergify[bot] avatar scala-steward avatar theinemann avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

fs2-cron's Issues

Allow specification of timezones for Cron schedule

Right now the library is hard-coded to use the local time for the cron schedule, but there are use cases where it's important that another timezone is used (especially UTC). Hence, fs2-cron should allow the callers to specify a timezone.

Support using cats-effect's Clock for determination of current time

Right now, the fs2-cron uses LocalDateTime.now() to determine the current time of execution. This is somewhat consistent with the usual Cron scheduler on Unix, however the implementation requires a Timer already for most times, which gives access to a Clock object that allows to retrieve the current time.

Using the Clock from the injected Timer would have the advantage that, depending on the Timer used, the user of the library can decide which time zone should be used, e.g. in case they want to base the schedule on UTC rather than local time.

A disadvantage is that the default implementation provided by cats-effect uses Java's currentTimeMillis, which is based on UTC time instead of local time, so it might be somewhat difficult to realise this without breaking the API.

release fs2-cron-cron4s for Scala 3

Hi, it looks to me like nothing is blocking a Scala 3 release?

Let me know if there's something I can do to make it happen :) (it's blocking an upgrade for me)

Cancel a schedule on demand

I am making a web backend, and trying to run tasks (lots of cron tasks) on cron schedule. How should I:

  • Add a new schedule to the group of existing schedules?
  • Remove, or reschedule an existing schedule on demand?

In the example, the interruptWhen is controlled by a signal within the same for-comprehension. How can I instead control this signal outside, upon receiving a new http request?

Support Scala 2.11

fs2-cron looks perfect for something I'm trying to do. Unfortunately the project I'd like to use it in is tied to 2.11 and fs2-cron is currently only published for 2.12.

If it's not a priority for you, would you welcome a PR tackling this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.