{"id":18950217,"url":"https://github.com/salesforce/centrifuge","last_synced_at":"2025-04-16T00:31:32.339Z","repository":{"id":40966249,"uuid":"149647886","full_name":"salesforce/centrifuge","owner":"salesforce","description":"JVM Warmup Engine","archived":false,"fork":false,"pushed_at":"2023-06-14T22:29:32.000Z","size":136,"stargazers_count":24,"open_issues_count":4,"forks_count":10,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-04-08T00:12:32.036Z","etag":null,"topics":["java","jit","jvm","warmup"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salesforce.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null}},"created_at":"2018-09-20T17:45:49.000Z","updated_at":"2024-04-01T16:20:54.000Z","dependencies_parsed_at":"2023-09-24T16:57:03.378Z","dependency_job_id":null,"html_url":"https://github.com/salesforce/centrifuge","commit_stats":{"total_commits":29,"total_committers":5,"mean_commits":5.8,"dds":0.4482758620689655,"last_synced_commit":"b4037c4dbe693288006638d8fb760e8f0c6c7cf8"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforce%2Fcentrifuge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforce%2Fcentrifuge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforce%2Fcentrifuge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforce%2Fcentrifuge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salesforce","download_url":"https://codeload.github.com/salesforce/centrifuge/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223690180,"owners_count":17186572,"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":["java","jit","jvm","warmup"],"created_at":"2024-11-08T13:21:45.933Z","updated_at":"2024-11-08T13:21:46.856Z","avatar_url":"https://github.com/salesforce.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Centrifuge Warmup Engine\n\nCentrifuge is a framework for scheduling and running startup and warmup tasks.\nIt is focused mainly on accelerating JVM restarts, and provides an interface for \nimplementing warmup tasks, such as:\n\n- calling an HTTP endpoint\n- populating caches \n- handling pre-compilation tasks for generated code\n\nCentrifuge is responsible for executing these warmup tasks and managing threads.\n\n### How to Use Centrifuge\n\nFirst, include a Maven dependency for Centrifuge in your POM:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.salesforce.centrifuge\u003c/groupId\u003e\n    \u003cartifactId\u003ecentrifuge-core\u003c/artifactId\u003e\n    \u003cversion\u003e${centrifuge.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nNow implement the `Warmer` interface for each of your warmup tasks.\nMake sure your warmer class\n\n- has an accessible default constructor\n- does not swallow `InterruptedException`\n\n```java\npublic interface Warmer {\n\n    /**\n     * This method is called at the beginning of execution; if an exception\n     * is thrown, centrifuge yields, and then retries calling init, until maximum\n     * number of failures allowed is reached.\n     *\n     * @param params parameters passed from config file\n     */\n    void init(final Map\u003cString, Object\u003e params) throws Exception;\n\n    /**\n     * This method is called as often as the number of iterations (config);\n     * or until the max failure (exception thrown) is reached (config);\n     * or until the max timeout for this warmer is reached (config);\n     * or until the max timeout for engine is reached (config).\n     */\n    void next() throws Exception;\n}\n```\n\nYou can register your warmers either programmatically, with code,\nor descriptively, with a configuration file. To register a warmer programmatically,\nwrite code like this:\n\n```java\npublic static void main(final String[] args) throws Exception {\n\n    // warmer config contains configurations used to execute a warmer\n    final WarmerConfig warmerConfig = new WarmerConfig();\n    warmerConfig.setWarmerClass(EchoWarmer.class);\n    warmerConfig.setMaxIterations(10);\n    warmerConfig.setMaxFailure(3);\n    warmerConfig.setTimeoutMillis(1000);\n    warmerConfig.setRequired(true);\n    \n    // parameters to be passed to warmer on initialization\n    final Map\u003cString, Object\u003e params = new HashMap\u003c\u003e();\n    params.put(\"text\", \"echo is a sample warmer...\");\n    warmerConfig.setParams(params);\n\n    final CentrifugeConfig centrifugeConfig = new CentrifugeConfig();\n    // add the warmer config from ^^ to centrifuge config\n    centrifugeConfig.addWarmerConfig(warmerConfig);\n\n    // get a new instance and start the engine\n    final Centrifuge centrifuge = Centrifuge.newInstance(centrifugeConfig);\n    centrifuge.start();\n\n    // check whether all *required* warmers are stopped (either completed successfully or reached maximum failure)\n    // note that *non-required* warmers may still be running and will continue to run\n    while (!centrifuge.isWarm()) {\n        // wait until is warm, then ping up to be put into rotation\n    }\n}\n```\n\nRegistering warmers descriptively within a configuration file lets you add and remove warmers without \nrecompiling. To register a warmer descriptively, create a `centrifuge.conf` configuration file that looks\nlike this:\n\n```java\n// configuration for warmup engine\ncentrifuge {\n\n  warmers = [\n    {\n      // warmer class name (required)\n      class = \"com.salesforce.centrifuge.EchoWarmer\"  // echo warmer is a simple example warmer\n      \n      // flag to tell centrifuge that this warmer has to finish executing before app is warm (optional, default = false)\n      required = false\n      \n      // maximum number of iterations to call the next() method (optional, default = 1)\n      max_iterations = 100\n      \n      // maximum cumulative execution time to run this warmer (optional, default = Long.MAX_VALUE)\n      timeout_millis = 500\n      \n      // time to yield before calling next() and init() to prevent exhausting resources (optional, default = 100)\n      yield_millis = 10\n      \n      // maximum number of failures allowed before stopping warmer (optional, default = 3)\n      max_failure = 1\n      \n      // number of concurrent threads to run this warmer (optional, default = 1)\n      concurrency = 3\n      \n      // custom parameters to be passed to warmers init() method as a map (optional, default = Collections.emptyMap())\n      params = {\n        text = \"hello world!\"\n      }\n    }\n  ]\n}\n```\n\nThen load the configuration file into Centrifuge like this:\n\n```java\npublic static void main(final String[] args) throws Exception {\n\n    // config for engine is loaded from the path given\n    final CentrifugeConfig centrifugeConfig = new CentrifugeConfig(\"centrifuge.conf\");\n\n    // create an instance and start\n    final Centrifuge centrifuge = Centrifuge.newInstance(centrifugeConfig);\n    centrifuge.start();\n    \n    // ...\n    \n    // check whether all *required* warmers have successfully completed\n    // note that *non-required* warmers may still be running and will continue to run\n    while (!centrifuge.isWarm()) {\n        // wait until is warm, then ping up to be put into rotation\n    }\n}\n```\n\n#### HTTP Warmer\n\nWe provide a simple HTTP warmer to call HTTP endpoints in order to trigger code path exercised by the\nresource implementing the endpoint.\n\nInclude this Maven dependency to pull the HTTP warmer into your project:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.salesforce.centrifuge\u003c/groupId\u003e\n    \u003cartifactId\u003ecentrifuge-warmers\u003c/artifactId\u003e\n    \u003cversion\u003e${centrifuge.version}\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nSuppose an application provides a homepage URL that, when called, performs\nbasic initialization, connects to a database, populates caches, etc. The HTTP warming can warm these \ncode paths simply by using the HTTP warmer to hit the homepage endpoint a sufficiently large number of times.\nThe following configuration file sets up the HTTP warmer to do this:\n\n```java\n{\n  class = \"com.salesforce.centrifuge.warmers.HttpWarmer\"\n  max_iterations = 1000  // make maximum of 1000 http calls\n  timeout_millis = 30000  // kill after 30 seconds\n  params = {\n    method = \"post\"\n    urls = [ \"http://localhost:8080/foo/bar\", \"http://localhost:8080/bar/baz\" ]\n    body = \"{ 'foo': 'bar' }\"\n    headers = {\n      Content-Type = \"application/json\"\n    }\n  }\n}\n```\n\n### Want to Contribute to Centrifuge?\n\nJust clone the repository:\n```bash\n$ git clone https://github.com/salesforce/centrifuge.git\n```\n\nThen compile and test like this:\n```bash\n$ cd centrifuge/\n$ ./bang.sh\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesforce%2Fcentrifuge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalesforce%2Fcentrifuge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesforce%2Fcentrifuge/lists"}