{"id":13504881,"url":"https://github.com/twitter/util","last_synced_at":"2025-05-12T15:32:52.877Z","repository":{"id":37818978,"uuid":"1527969","full_name":"twitter/util","owner":"twitter","description":"Wonderful reusable code from Twitter","archived":false,"fork":false,"pushed_at":"2025-04-21T03:10:33.000Z","size":30074,"stargazers_count":2717,"open_issues_count":14,"forks_count":582,"subscribers_count":224,"default_branch":"develop","last_synced_at":"2025-04-23T17:15:03.401Z","etag":null,"topics":["finagle","scala","utility"],"latest_commit_sha":null,"homepage":"https://twitter.github.io/util","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/twitter.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.rst","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null}},"created_at":"2011-03-26T01:23:21.000Z","updated_at":"2025-04-21T03:10:36.000Z","dependencies_parsed_at":"2023-02-02T20:46:11.591Z","dependency_job_id":"fc5942d1-29b7-4d7d-8cab-8b24986321a1","html_url":"https://github.com/twitter/util","commit_stats":{"total_commits":3003,"total_committers":328,"mean_commits":9.15548780487805,"dds":0.8787878787878788,"last_synced_commit":"7d74b9ce7dbaee1962eef81a9a6d562140e0a6b6"},"previous_names":[],"tags_count":99,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twitter%2Futil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twitter%2Futil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twitter%2Futil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twitter%2Futil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twitter","download_url":"https://codeload.github.com/twitter/util/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253765732,"owners_count":21960779,"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":["finagle","scala","utility"],"created_at":"2024-08-01T00:00:52.825Z","updated_at":"2025-05-12T15:32:52.846Z","avatar_url":"https://github.com/twitter.png","language":"Scala","readme":"# Twitter Util\n\n[![Build Status](https://github.com/twitter/util/workflows/continuous%20integration/badge.svg?branch=develop)](https://github.com/twitter/util/actions?query=workflow%3A%22continuous+integration%22+branch%3Adevelop)\n[![Project status](https://img.shields.io/badge/status-active-brightgreen.svg)](#status)\n[![Gitter](https://badges.gitter.im/twitter/finagle.svg)](https://gitter.im/twitter/finagle?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.twitter/util-core_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.twitter/util-core_2.12)\n\nA bunch of idiomatic, small, general purpose tools.\n\nSee the Scaladoc [here](https://twitter.github.io/util/docs/#com.twitter.util.package)\nor check out the [user guide](https://twitter.github.io/util).\n\n## Status\n\nThis project is used in production at Twitter (and many other organizations),\nand is being actively developed and maintained.\n\n## Releases\n\n[Releases](https://maven-badges.herokuapp.com/maven-central/com.twitter/util_2.12)\nare done on an approximately monthly schedule. While [semver](https://semver.org/)\nis not followed, the [changelogs](CHANGELOG.rst) are detailed and include sections on\npublic API breaks and changes in runtime behavior.\n\n## Contributing\n\nWe feel that a welcoming community is important and we ask that you follow Twitter's\n[Open Source Code of Conduct](https://github.com/twitter/.github/blob/main/code-of-conduct.md)\nin all interactions with the community.\n\nThe `release` branch of this repository contains the latest stable release of\nUtil, and weekly snapshots are published to the `develop` branch. In general\npull requests should be submitted against `develop`. See\n[CONTRIBUTING.md](https://github.com/twitter/util/blob/release/CONTRIBUTING.md)\nfor more details about how to contribute.\n\n# Using in your project\n\nAn example SBT dependency string for the `util-core` library would look like this:\n\n```scala\nval utilCore = \"com.twitter\" %% \"util-core\" % \"24.5.0\"\n```\n\n# Units\n\n## Time\n\n```scala\nimport com.twitter.conversions.DurationOps._\n\nval duration1 = 1.second\nval duration2 = 2.minutes\nduration1.inMillis // =\u003e 1000L\n```\n\n## Space\n\n```scala\nimport com.twitter.conversions.StorageUnitOps._\nval amount = 8.megabytes\namount.inBytes // =\u003e 8388608L\namount.inKilobytes // =\u003e 8192L\n```\n\n# Futures\n\nA Non-actor re-implementation of Scala Futures.\n\n```scala\nimport com.twitter.conversions.DurationOps._\nimport com.twitter.util.{Await, Future, Promise}\n\nval f = new Promise[Int]\nval g = f.map { result =\u003e result + 1 }\nf.setValue(1)\nAwait.result(g, 1.second) // =\u003e this blocks for the futures result (and eventually returns 2)\n\n// Another option:\ng.onSuccess { result =\u003e\n  println(result) // =\u003e prints \"2\"\n}\n\n// Using for expressions:\nval xFuture = Future(1)\nval yFuture = Future(2)\n\nfor {\n  x \u003c- xFuture\n  y \u003c- yFuture\n} {\n  println(x + y) // =\u003e prints \"3\"\n}\n```\n\n## Future interrupts\n\nMethod `raise` on `Future` (`def raise(cause: Throwable)`) raises the interrupt described by\n`cause` to the producer of this `Future`. Interrupt handlers are installed on a `Promise`\nusing `setInterruptHandler`, which takes a partial function:\n\n```scala\nval p = new Promise[T]\np.setInterruptHandler {\n  case exc: MyException =\u003e\n    // deal with interrupt..\n}\n```\n\nInterrupts differ in semantics from cancellation in important ways: there can only be one\ninterrupt handler per promise, and interrupts are only delivered if the promise is not yet\ncomplete.\n\n# Object Pool\n\nThe pool order is FIFO.\n\n## A pool of constants\n\n```scala\nimport scala.collection.mutable\nimport com.twitter.util.{Await, SimplePool}\n\nval queue = new mutable.Queue[Int] ++ List(1, 2, 3)\nval pool = new SimplePool(queue)\n\n// Note that the pool returns Futures, it doesn't block on exhaustion.\nassert(Await.result(pool.reserve()) == 1)\npool.reserve().onSuccess { item =\u003e\n  println(item) // prints \"2\"\n}\n```\n\n## A pool of dynamically created objects\n\nHere is a pool of even-number generators. It stores 4 numbers at a time:\n\n```scala\nimport com.twitter.util.{Future, FactoryPool}\n\nval pool = new FactoryPool[Int](4) {\n  var count = 0\n  def makeItem() = { count += 1; Future(count) }\n  def isHealthy(i: Int) = i % 2 == 0\n}\n```\n\nIt checks the health when you successfully reserve an object (i.e., when the Future yields).\n\n# Hashing\n\n`util-hashing` is a collection of hash functions and hashing distributors (eg. ketama).\n\nTo use one of the available hash functions:\n\n```scala\nimport com.twitter.hashing.KeyHasher\n\nKeyHasher.FNV1_32.hashKey(\"string\".getBytes)\n```\n\nAvailable hash functions are:\n\n```\nFNV1_32\nFNV1A_32\nFNV1_64\nFNV1A_64\nKETAMA\nCRC32_ITU\nHSIEH\n```\n\nTo use `KetamaDistributor`:\n\n```scala\nimport com.twitter.hashing.{KetamaDistributor, KetamaNode, KeyHasher}\n\nval nodes = List(KetamaNode(\"host:port\", 1 /* weight */, \"foo\" /* handle */))\nval distributor = new KetamaDistributor(nodes, 1 /* num reps */)\ndistributor.nodeForHash(\"abc\".##) // =\u003e client\n```\n\n# Time and Duration\n\nLike arithmetic on doubles, `Time` and `Duration` arithmetic is now free of overflows. Instead, they overflow to `Top` and `Bottom` values, which are analogous to positive and negative infinity.\n\nSince the resolution of `Time.now` has been reduced (and is also more expensive due to its use of system time), a new `Stopwatch` API has been introduced in order to calculate durations of time.\n\nIt's used simply:\n\n```scala\nimport com.twitter.util.{Duration, Stopwatch}\nval elapsed: () =\u003e Duration = Stopwatch.start()\n```\n\nwhich is read by applying `elapsed`:\n\n```scala\nval duration: Duration = elapsed()\n```\n\n## License\n\nCopyright 2010 Twitter, Inc.\n\nLicensed under the Apache License, Version 2.0: https://www.apache.org/licenses/LICENSE-2.0\n","funding_links":[],"categories":["Scala","Table of Contents","Extensions","工具库"],"sub_categories":["Misc","Extensions"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwitter%2Futil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwitter%2Futil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwitter%2Futil/lists"}