{"id":21948156,"url":"https://github.com/evolution-gaming/sequentially","last_synced_at":"2025-04-23T00:16:31.784Z","repository":{"id":29198994,"uuid":"120475930","full_name":"evolution-gaming/sequentially","owner":"evolution-gaming","description":"Constructions to run tasks sequentially","archived":false,"fork":false,"pushed_at":"2025-04-03T10:36:20.000Z","size":181,"stargazers_count":3,"open_issues_count":20,"forks_count":3,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-23T00:16:25.377Z","etag":null,"topics":["concurrency","scala","sequentially"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evolution-gaming.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-06T15:08:30.000Z","updated_at":"2025-04-03T10:36:24.000Z","dependencies_parsed_at":"2024-06-10T11:12:05.380Z","dependency_job_id":"3875538f-401e-4ad6-8ffe-3b89e7c561d5","html_url":"https://github.com/evolution-gaming/sequentially","commit_stats":null,"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evolution-gaming%2Fsequentially","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evolution-gaming%2Fsequentially/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evolution-gaming%2Fsequentially/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evolution-gaming%2Fsequentially/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evolution-gaming","download_url":"https://codeload.github.com/evolution-gaming/sequentially/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250343960,"owners_count":21415042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["concurrency","scala","sequentially"],"created_at":"2024-11-29T05:12:13.939Z","updated_at":"2025-04-23T00:16:31.761Z","avatar_url":"https://github.com/evolution-gaming.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Sequentially\n[![Build Status](https://github.com/evolution-gaming/sequentially/workflows/CI/badge.svg)](https://github.com/evolution-gaming/sequentially/actions?query=workflow%3ACI)\n[![Coverage Status](https://coveralls.io/repos/evolution-gaming/sequentially/badge.svg)](https://coveralls.io/r/evolution-gaming/sequentially)\n[![Codacy Badge](https://app.codacy.com/project/badge/Grade/ad6385e8c3a34c5ab99009062a13d37c)](https://app.codacy.com/gh/evolution-gaming/sequentially/dashboard?utm_source=gh\u0026utm_medium=referral\u0026utm_content=\u0026utm_campaign=Badge_grade)\n[![Version](https://img.shields.io/badge/version-click-blue)](https://evolution.jfrog.io/artifactory/api/search/latestVersion?g=com.evolutiongaming\u0026a=sequentially_2.13\u0026repos=public)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellowgreen.svg)](https://opensource.org/licenses/MIT)\n\nThis library contains `Sequentially.scala` which allows running tasks sequentially for the same key and in parallel for different keys\nThe behavior is somehow similar to what actors propose, however it provides typesafety.\nAlso, it is easy to write tests using `Sequentially.now` to avoid an unnecessary concurrency.   \n\n```scala\ntrait Sequentially[-K] {\n  def apply[KK \u003c: K, T](key: KK)(task: =\u003e T): Future[T]\n}\n```\n\n## Example\n\nThis example explains how we can ensure that there are no concurrent updates to `var state`\n\n```scala\ntype Key = Unit // ok for example\nval system = ActorSystem() // yes, we have dependency on akka\nval sequentially = Sequentially[Key](system)\n\nvar state: Int = 0\n\n// this runs sequentially, like message handling in actors \nsequentially(()) {\n state = state + 1\n}\n\n// you also can expose computation result as Future[T]\nval stateBefore: Future[Int] = sequentially(()) {\n  val stateBefore = state\n  state = state + 1\n  stateBefore\n} \n```\n\n## Other good stuff\n\nWe usually have more complicated requirements in real life applications, \nthus we have implemented  more powerful `Sequentially-like` structures\n\n```scala\ntrait SequentiallyAsync[-K] extends Sequentially[K] {\n\n  def async[KK \u003c: K, T](key: K)(task: =\u003e Future[T]): Future[T]\n}\n```\n\n```scala\ntrait SequentiallyHandler[-K] extends SequentiallyAsync[K] {\n\n  def handler[KK \u003c: K, T](key: KK)(task: =\u003e Future[() =\u003e Future[T]]): Future[T]\n}\n```\n\nAnd also we have mixed `TrieMap` with `Sequentially`, results can be found in\n\n* AsyncMap.scala\n* SequentialMap.scala\n* AsyncHandlerMap.scala      \n\n  \n## Setup\n\n```scala\naddSbtPlugin(\"com.evolution\" % \"sbt-artifactory-plugin\" % \"0.0.2\")\n\nlibraryDependencies += \"com.evolutiongaming\" %% \"sequentially\" % \"1.2.0\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevolution-gaming%2Fsequentially","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevolution-gaming%2Fsequentially","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevolution-gaming%2Fsequentially/lists"}