{"id":15439507,"url":"https://github.com/joelittlejohn/party","last_synced_at":"2025-12-12T01:10:00.670Z","repository":{"id":62433674,"uuid":"41870760","full_name":"joelittlejohn/party","owner":"joelittlejohn","description":"A Clojure library that wraps the Curator service discovery/registration API and provides a set of Clojure functions to quickly and easily discover/register a service/resource","archived":false,"fork":false,"pushed_at":"2016-04-28T23:16:50.000Z","size":52,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-18T11:23:59.954Z","etag":null,"topics":["clojure","curator","microservices","service-discovery","zookeeper"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","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/joelittlejohn.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}},"created_at":"2015-09-03T16:29:35.000Z","updated_at":"2020-11-09T09:14:42.000Z","dependencies_parsed_at":"2022-11-01T21:16:11.505Z","dependency_job_id":null,"html_url":"https://github.com/joelittlejohn/party","commit_stats":null,"previous_names":["mixradio/party"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelittlejohn%2Fparty","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelittlejohn%2Fparty/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelittlejohn%2Fparty/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelittlejohn%2Fparty/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joelittlejohn","download_url":"https://codeload.github.com/joelittlejohn/party/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241329410,"owners_count":19944984,"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":["clojure","curator","microservices","service-discovery","zookeeper"],"created_at":"2024-10-01T19:07:04.426Z","updated_at":"2025-12-12T01:09:55.621Z","avatar_url":"https://github.com/joelittlejohn.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# party\n\n\u003cimg src=\"https://upload.wikimedia.org/wikipedia/commons/c/c3/Party_icon.svg\" alt=\"Let's party!\" title=\"Let's party!\" align=\"right\" width=\"250\"/\u003e\n\nA Clojure library that wraps the Curator service discovery/registration API and provides a set of Clojure functions to register and discover services. \n\nParty also helps manage the lifecycle of the CuratorFramework internally, creating and maintaining connections to Zookeeper as necessary and closing those connections when your application terminates.\n\n![latest version](https://clojars.org/mixradio/party/latest-version.svg)\n\n## Usage\n\n#### A typical _registration_ example\n\nA service registering:\n\n```clj\n(ns heartbeat.setup\n  (:require [party.registration :as party])\n\n(defn register-public-resources []\n  (party/connect!)\n  \n  ;; if you want to register the entire service (no uri-spec)\n  (party/register! {:name \"foo\"\n                    :port (Integer. (env :service-port)))\n                     \n  ;; if you want to register a specific resource\n  (party/register! {:name \"user-sessions\"\n                    :port (Integer. (env :service-port))\n                    :uri-spec \"/1.x/{territory}/users/{userid}/sessions/{devicetype}/{app}\"}))\n                     \n(defn start []\n  (setup)\n  (reset! server (start-server))\n  (register-public-resources))\n```\n\n`party.registration/connect!` uses the [environ](https://github.com/weavejester/environ) properties `:zookeeper-connectionstring` and `:environment-name`. An alternative to setting them in your project.clj file (or as system variables via a bash script) is to provide these two values directly as arguments to the function call.\n\nServices that use `party.registration` should add a call to `(party.registration/healthy?)` to their healthcheck. Note from the above that the `uri-spec` is optional, if you want to register an entire service (rather than an individual resource) and allow clients to construct the paths themselves, then omit the `uri-spec`.\n\nYou can also use a healthcheck function which must return truthy before registration will succeed. If the healthcheck function returns falsey, 10 attemps will be made to register, one second apart (override with `:party-registration-attempts` environ key):\n\n```clj\n(defn register-public-resources []\n  (party/connect!)\n  (party/register! {:name \"user-sessions\"\n                    :port (Integer. (env :service-port))\n                    :uri-spec \"/1.x/{territory}/users/{userid}/sessions/{devicetype}/{app}\"}\n                     #(-\u003e (web/healthcheck) :success))\n```\n\n#### A typical _discovery_ example\n\nService _x_ finding an instance of service _y_ to handle a request:\n\n```clj\n(ns x.setup\n  (:require [party.discovery :as party])\n\n(defn setup []\n  ...\n  (party/connect!))\n```\n\n```clj\n(ns x.core\n  (:require [clj-http.client :as http]\n            [party.discovery :as party])\n\n(defn fn-that-calls-y [territory]\n  ;; if you want to construct your own path\n  (http/get (party/base-url+ \"y\" \"/1.x/\" territory \"/foo\"))\n\n  ;; if you want to build the path using the registered uri-spec\n  (http/get (party/url \"y\" {:territory territory)))\n\n  ;; if you want to do something completely bespoke\n  (with-open [service-provider (party/service-provider \"y\")]\n    (let [instance (.getInstance service-provider)]\n      ;; do something with instance\n      )))\n\n```\n\nServices that use `party.discovery` should add a call to `(party.discovery/healthy?)` to their healthcheck.\n\n**IMPORTANT: When you use party for discovery you are building a URL using an IP address that is only valid for the current call. IP addresses can change at any time, and your calls _should_ be balanced across all IPs. Don't _ever_ save URLs produced by `url` or `base-url+` for later use. Get a new one each time.**\n\n## Graceful shutdown\n\nWhen you register for service discovery it's essential that your instances disconnect gracefully (e.g. when your sevice is deployed and old instances are shut down, you shouldn't see a short period of downtime). You must disconnect from service discovery **before** Jetty begins rejecting incoming requests.\n\nIf you're using [instrumented-ring-jetty-adapter](https://github.com/mixradio/instrumented-ring-jetty-adapter) then you can create a safe shutdown like:\n\n```clj\n(defn configure-server [server]\n  (doto server\n    (.setStopAtShutdown true)\n    (.setGracefulShutdown (Integer/valueOf (env :service-jetty-gracefulshutdown-millis)))))\n\n(defn unregister-public-resources\n  []\n  (party/disconnect!)\n  (Thread/sleep (Integer/valueOf (env :service-curator-gracefulunregister-millis))))\n\n(defn start-server []\n  (instrumented/run-jetty #'web/app {...\n                                     :configurator configure-server\n                                     :on-stop unregister-public-resources}))\n```\n\n## Testing\n\nFor functional testing, it's often useful to skip service discovery and provide an explicit URL. For a service `foo`, you can override the URL like:\n\n```\n:discovery-override-foo \"http://localhost:8081/1.x/foo/{bar}/baz\"\n```\n\nSince we use environ, the same can be achieved using `export DISCOVERY_OVERRIDE_FOO` or `-Ddiscovery.override.foo`. The path (`/1.x/foo/{bar}/baz`) is of course optional.\n\nSince we're effectively skipping the discovery step here, it's recommended that you have a least some tests that fully integrate and _do_ exercise the discovery mechanism.\n\n# License\n\nCopyright © 2015 MixRadio\n\nparty is released under the 3-clause license (\"New BSD License\" or \"Modified BSD License\")\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelittlejohn%2Fparty","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoelittlejohn%2Fparty","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelittlejohn%2Fparty/lists"}