{"action":"created","comment":{"url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/comments/27686514","id":27686514,"diff_hunk":"@@ -0,0 +1,142 @@\n+(ns puppetlabs.services.jruby.jruby-puppet-schemas\n+  (:require [schema.core :as schema]\n+            [puppetlabs.services.jruby.puppet-environments :as puppet-env])\n+  (:import (java.util.concurrent BlockingDeque)\n+           (clojure.lang Atom Agent)\n+           (com.puppetlabs.puppetserver PuppetProfiler JRubyPuppet EnvironmentRegistry)\n+           (org.jruby.embed ScriptingContainer)))\n+\n+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n+;;; Schemas\n+\n+(def pool-queue-type\n+  \"The Java datastructure type used to store JRubyPuppet instances which are\n+  free to be borrowed.\"\n+  BlockingDeque)\n+\n+(defrecord PoisonPill\n+  ;; A sentinel object to put into a pool in case an error occurs while we're trying\n+  ;; to populate it.  This can be used by the `borrow` functions to detect error\n+  ;; state in a thread-safe manner.\n+  [err])\n+\n+(defrecord RetryPoisonPill\n+  ;; A sentinel object to put into an old pool when we swap in a new pool.\n+  ;; This can be used to build `borrow` functionality that will detect the\n+  ;; case where we're trying to borrow from an old pool, so that we can retry\n+  ;; with the new pool.\n+  [pool])\n+\n+(def JRubyPuppetConfig\n+  \"Schema defining the config map for the JRubyPuppet pooling functions.\n+\n+  The keys should have the following values:\n+\n+    * :ruby-load-path - a vector of file paths, containing the locations of puppet source code.\n+\n+    * :gem-home - The location that JRuby gems are stored\n+\n+    * :master-conf-dir - file path to puppetmaster's conf dir;\n+        if not specified, will use the puppet default.\n+\n+    * :master-var-dir - path to the puppetmaster' var dir;\n+        if not specified, will use the puppet default.\n+\n+    * :max-active-instances - The maximum number of JRubyPuppet instances that\n+        will be pooled. If not specified, the system's\n+        number of CPUs+2 will be used.\n+\n+    * :http-client-ssl-protocols - A list of legal SSL protocols that may be used\n+        when https client requests are made.\n+\n+    * :http-client-cipher-suites - A list of legal SSL cipher suites that may\n+        be used when https client requests are made.\"\n+  {:ruby-load-path              (schema/both [schema/Str] (schema/pred vector?))\n+   :gem-home                    schema/Str\n+   :master-conf-dir             (schema/maybe schema/Str)\n+   :master-var-dir              (schema/maybe schema/Str)\n+   :http-client-ssl-protocols   [schema/Str]\n+   :http-client-cipher-suites   [schema/Str]\n+   :max-active-instances        schema/Int\n+   :max-requests-per-instance   schema/Int})\n+\n+(def JRubyPoolAgent\n+  \"An agent configured for use in managing JRuby pools\"\n+  (schema/both Agent\n+               (schema/pred\n+                 (fn [a]\n+                   (let [state @a]\n+                     (and\n+                       (map? state)\n+                       (ifn? (:shutdown-on-error state))))))))\n+\n+(def PoolState\n+  \"A map that describes all attributes of a particular JRubyPuppet pool.\"\n+  {:pool         pool-queue-type\n+   :size schema/Int})\n+\n+(def PoolStateContainer\n+  \"An atom containing the current state of all of the JRubyPuppet pool.\"\n+  (schema/pred #(and (instance? Atom %)\n+                     (nil? (schema/check PoolState @%)))\n+               'PoolStateContainer))\n+\n+(def PoolContext\n+  \"The data structure that stores all JRubyPuppet pools and the original configuration.\"\n+  {:config                JRubyPuppetConfig\n+   :profiler              (schema/maybe PuppetProfiler)\n+   :pool-agent            JRubyPoolAgent\n+   :flush-instance-agent  JRubyPoolAgent\n+   :pool-state            PoolStateContainer})\n+\n+(def JRubyInstanceState\n+  \"State metadata for an individual JRubyPuppet instance\"\n+  {:request-count schema/Int})\n+\n+(def JRubyInstanceStateContainer\n+  \"An atom containing the current state of a given JRubyPuppet instance.\"\n+  (schema/pred #(and (instance? Atom %)\n+                     (nil? (schema/check JRubyInstanceState @%)))\n+               'JRubyInstanceState))\n+\n+;; A record representing an individual entry in the JRubyPuppet pool.\n+(schema/defrecord JRubyPuppetInstance\n+                  [pool :- pool-queue-type\n+                   id :- schema/Int\n+                   state :- JRubyInstanceStateContainer\n+                   jruby-puppet :- JRubyPuppet\n+                   scripting-container :- ScriptingContainer\n+                   environment-registry :- (schema/both\n+                                             EnvironmentRegistry\n+                                             (schema/pred\n+                                               #(satisfies? puppet-env/EnvironmentStateContainer %)))]\n+                  Object\n+                  (toString [this] (format \"%s@%s {:id %s :state (Atom: %s)}\"\n+                                           \"puppetlabs.services.jruby.jruby_puppet_core.JRubyPuppetInstance\"","path":"src/clj/puppetlabs/services/jruby/jruby_puppet_schemas.clj","position":115,"original_position":115,"commit_id":"2980a78dbb727dd1916da62568941dfee82206a0","original_commit_id":"2980a78dbb727dd1916da62568941dfee82206a0","user":{"login":"cprice404","id":1341071,"avatar_url":"https://avatars.githubusercontent.com/u/1341071?v=3","gravatar_id":"","url":"https://api.github.com/users/cprice404","html_url":"https://github.com/cprice404","followers_url":"https://api.github.com/users/cprice404/followers","following_url":"https://api.github.com/users/cprice404/following{/other_user}","gists_url":"https://api.github.com/users/cprice404/gists{/gist_id}","starred_url":"https://api.github.com/users/cprice404/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cprice404/subscriptions","organizations_url":"https://api.github.com/users/cprice404/orgs","repos_url":"https://api.github.com/users/cprice404/repos","events_url":"https://api.github.com/users/cprice404/events{/privacy}","received_events_url":"https://api.github.com/users/cprice404/received_events","type":"User","site_admin":false},"body":"Fixed in my next PR.","created_at":"2015-04-02T18:57:25Z","updated_at":"2015-04-02T18:57:25Z","html_url":"https://github.com/puppetlabs/puppet-server/pull/416#discussion_r27686514","pull_request_url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416","_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/comments/27686514"},"html":{"href":"https://github.com/puppetlabs/puppet-server/pull/416#discussion_r27686514"},"pull_request":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416"}}},"pull_request":{"url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416","id":30028989,"html_url":"https://github.com/puppetlabs/puppet-server/pull/416","diff_url":"https://github.com/puppetlabs/puppet-server/pull/416.diff","patch_url":"https://github.com/puppetlabs/puppet-server/pull/416.patch","issue_url":"https://api.github.com/repos/puppetlabs/puppet-server/issues/416","number":416,"state":"closed","locked":false,"title":"(FOR REVIEW) (SERVER-325) flush jrubies after max requests","user":{"login":"cprice404","id":1341071,"avatar_url":"https://avatars.githubusercontent.com/u/1341071?v=3","gravatar_id":"","url":"https://api.github.com/users/cprice404","html_url":"https://github.com/cprice404","followers_url":"https://api.github.com/users/cprice404/followers","following_url":"https://api.github.com/users/cprice404/following{/other_user}","gists_url":"https://api.github.com/users/cprice404/gists{/gist_id}","starred_url":"https://api.github.com/users/cprice404/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cprice404/subscriptions","organizations_url":"https://api.github.com/users/cprice404/orgs","repos_url":"https://api.github.com/users/cprice404/repos","events_url":"https://api.github.com/users/cprice404/events{/privacy}","received_events_url":"https://api.github.com/users/cprice404/received_events","type":"User","site_admin":false},"body":"NOTE: not ready for merge; need to clean up some of the last few commits and add a few more tests.\r\n\r\n---------------------\r\n\r\nThis PR does the following:\r\n\r\n* Change our JRuby queuing strategy from FIFO to LIFO.  (This improves memory usage by a great deal when the system is not under high load, and also makes it possible for us to flush individual JRuby instances after a maximum number of requests in a sane way; in a FIFO model, all JRuby instances would hit the max number of requests at roughly the same time.)\r\n* Refactors a lot of the JRuby code to make it possible to flush instances with more granularity than the entire pool\r\n* Introduce a setting 'max-requests-per-instance'; after any JRuby instance handles more requests than this, it will be flushed and replaced in the pool by a fresh one","created_at":"2015-02-25T21:52:20Z","updated_at":"2015-04-02T18:57:25Z","closed_at":"2015-03-16T15:55:23Z","merged_at":null,"merge_commit_sha":"94e81fd690a5fe9ce26b4673fc0b1e4ad7c6da8d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416/commits","review_comments_url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416/comments","review_comment_url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/comments{/number}","comments_url":"https://api.github.com/repos/puppetlabs/puppet-server/issues/416/comments","statuses_url":"https://api.github.com/repos/puppetlabs/puppet-server/statuses/2980a78dbb727dd1916da62568941dfee82206a0","head":{"label":"cprice404:feature/stable/SERVER-325-flush-jrubies-after-max-requests","ref":"feature/stable/SERVER-325-flush-jrubies-after-max-requests","sha":"2980a78dbb727dd1916da62568941dfee82206a0","user":{"login":"cprice404","id":1341071,"avatar_url":"https://avatars.githubusercontent.com/u/1341071?v=3","gravatar_id":"","url":"https://api.github.com/users/cprice404","html_url":"https://github.com/cprice404","followers_url":"https://api.github.com/users/cprice404/followers","following_url":"https://api.github.com/users/cprice404/following{/other_user}","gists_url":"https://api.github.com/users/cprice404/gists{/gist_id}","starred_url":"https://api.github.com/users/cprice404/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cprice404/subscriptions","organizations_url":"https://api.github.com/users/cprice404/orgs","repos_url":"https://api.github.com/users/cprice404/repos","events_url":"https://api.github.com/users/cprice404/events{/privacy}","received_events_url":"https://api.github.com/users/cprice404/received_events","type":"User","site_admin":false},"repo":{"id":24339614,"name":"puppet-server","full_name":"cprice404/puppet-server","owner":{"login":"cprice404","id":1341071,"avatar_url":"https://avatars.githubusercontent.com/u/1341071?v=3","gravatar_id":"","url":"https://api.github.com/users/cprice404","html_url":"https://github.com/cprice404","followers_url":"https://api.github.com/users/cprice404/followers","following_url":"https://api.github.com/users/cprice404/following{/other_user}","gists_url":"https://api.github.com/users/cprice404/gists{/gist_id}","starred_url":"https://api.github.com/users/cprice404/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cprice404/subscriptions","organizations_url":"https://api.github.com/users/cprice404/orgs","repos_url":"https://api.github.com/users/cprice404/repos","events_url":"https://api.github.com/users/cprice404/events{/privacy}","received_events_url":"https://api.github.com/users/cprice404/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cprice404/puppet-server","description":"Server automation framework and application","fork":true,"url":"https://api.github.com/repos/cprice404/puppet-server","forks_url":"https://api.github.com/repos/cprice404/puppet-server/forks","keys_url":"https://api.github.com/repos/cprice404/puppet-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cprice404/puppet-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cprice404/puppet-server/teams","hooks_url":"https://api.github.com/repos/cprice404/puppet-server/hooks","issue_events_url":"https://api.github.com/repos/cprice404/puppet-server/issues/events{/number}","events_url":"https://api.github.com/repos/cprice404/puppet-server/events","assignees_url":"https://api.github.com/repos/cprice404/puppet-server/assignees{/user}","branches_url":"https://api.github.com/repos/cprice404/puppet-server/branches{/branch}","tags_url":"https://api.github.com/repos/cprice404/puppet-server/tags","blobs_url":"https://api.github.com/repos/cprice404/puppet-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cprice404/puppet-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cprice404/puppet-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/cprice404/puppet-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cprice404/puppet-server/statuses/{sha}","languages_url":"https://api.github.com/repos/cprice404/puppet-server/languages","stargazers_url":"https://api.github.com/repos/cprice404/puppet-server/stargazers","contributors_url":"https://api.github.com/repos/cprice404/puppet-server/contributors","subscribers_url":"https://api.github.com/repos/cprice404/puppet-server/subscribers","subscription_url":"https://api.github.com/repos/cprice404/puppet-server/subscription","commits_url":"https://api.github.com/repos/cprice404/puppet-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/cprice404/puppet-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/cprice404/puppet-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/cprice404/puppet-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/cprice404/puppet-server/contents/{+path}","compare_url":"https://api.github.com/repos/cprice404/puppet-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cprice404/puppet-server/merges","archive_url":"https://api.github.com/repos/cprice404/puppet-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cprice404/puppet-server/downloads","issues_url":"https://api.github.com/repos/cprice404/puppet-server/issues{/number}","pulls_url":"https://api.github.com/repos/cprice404/puppet-server/pulls{/number}","milestones_url":"https://api.github.com/repos/cprice404/puppet-server/milestones{/number}","notifications_url":"https://api.github.com/repos/cprice404/puppet-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cprice404/puppet-server/labels{/name}","releases_url":"https://api.github.com/repos/cprice404/puppet-server/releases{/id}","created_at":"2014-09-22T18:11:20Z","updated_at":"2015-03-10T00:18:47Z","pushed_at":"2015-04-02T18:54:28Z","git_url":"git://github.com/cprice404/puppet-server.git","ssh_url":"git@github.com:cprice404/puppet-server.git","clone_url":"https://github.com/cprice404/puppet-server.git","svn_url":"https://github.com/cprice404/puppet-server","homepage":"","size":2658,"stargazers_count":0,"watchers_count":0,"language":"Clojure","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"puppetlabs:stable","ref":"stable","sha":"d2b0f2196cad8d708706cdc1ef5ac97532c4c895","user":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":19546488,"name":"puppet-server","full_name":"puppetlabs/puppet-server","owner":{"login":"puppetlabs","id":234268,"avatar_url":"https://avatars.githubusercontent.com/u/234268?v=3","gravatar_id":"","url":"https://api.github.com/users/puppetlabs","html_url":"https://github.com/puppetlabs","followers_url":"https://api.github.com/users/puppetlabs/followers","following_url":"https://api.github.com/users/puppetlabs/following{/other_user}","gists_url":"https://api.github.com/users/puppetlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/puppetlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/puppetlabs/subscriptions","organizations_url":"https://api.github.com/users/puppetlabs/orgs","repos_url":"https://api.github.com/users/puppetlabs/repos","events_url":"https://api.github.com/users/puppetlabs/events{/privacy}","received_events_url":"https://api.github.com/users/puppetlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/puppetlabs/puppet-server","description":"Server automation framework and application","fork":false,"url":"https://api.github.com/repos/puppetlabs/puppet-server","forks_url":"https://api.github.com/repos/puppetlabs/puppet-server/forks","keys_url":"https://api.github.com/repos/puppetlabs/puppet-server/keys{/key_id}","collaborators_url":"https://api.github.com/repos/puppetlabs/puppet-server/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/puppetlabs/puppet-server/teams","hooks_url":"https://api.github.com/repos/puppetlabs/puppet-server/hooks","issue_events_url":"https://api.github.com/repos/puppetlabs/puppet-server/issues/events{/number}","events_url":"https://api.github.com/repos/puppetlabs/puppet-server/events","assignees_url":"https://api.github.com/repos/puppetlabs/puppet-server/assignees{/user}","branches_url":"https://api.github.com/repos/puppetlabs/puppet-server/branches{/branch}","tags_url":"https://api.github.com/repos/puppetlabs/puppet-server/tags","blobs_url":"https://api.github.com/repos/puppetlabs/puppet-server/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/puppetlabs/puppet-server/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/puppetlabs/puppet-server/git/refs{/sha}","trees_url":"https://api.github.com/repos/puppetlabs/puppet-server/git/trees{/sha}","statuses_url":"https://api.github.com/repos/puppetlabs/puppet-server/statuses/{sha}","languages_url":"https://api.github.com/repos/puppetlabs/puppet-server/languages","stargazers_url":"https://api.github.com/repos/puppetlabs/puppet-server/stargazers","contributors_url":"https://api.github.com/repos/puppetlabs/puppet-server/contributors","subscribers_url":"https://api.github.com/repos/puppetlabs/puppet-server/subscribers","subscription_url":"https://api.github.com/repos/puppetlabs/puppet-server/subscription","commits_url":"https://api.github.com/repos/puppetlabs/puppet-server/commits{/sha}","git_commits_url":"https://api.github.com/repos/puppetlabs/puppet-server/git/commits{/sha}","comments_url":"https://api.github.com/repos/puppetlabs/puppet-server/comments{/number}","issue_comment_url":"https://api.github.com/repos/puppetlabs/puppet-server/issues/comments{/number}","contents_url":"https://api.github.com/repos/puppetlabs/puppet-server/contents/{+path}","compare_url":"https://api.github.com/repos/puppetlabs/puppet-server/compare/{base}...{head}","merges_url":"https://api.github.com/repos/puppetlabs/puppet-server/merges","archive_url":"https://api.github.com/repos/puppetlabs/puppet-server/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/puppetlabs/puppet-server/downloads","issues_url":"https://api.github.com/repos/puppetlabs/puppet-server/issues{/number}","pulls_url":"https://api.github.com/repos/puppetlabs/puppet-server/pulls{/number}","milestones_url":"https://api.github.com/repos/puppetlabs/puppet-server/milestones{/number}","notifications_url":"https://api.github.com/repos/puppetlabs/puppet-server/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/puppetlabs/puppet-server/labels{/name}","releases_url":"https://api.github.com/repos/puppetlabs/puppet-server/releases{/id}","created_at":"2014-05-07T19:00:24Z","updated_at":"2015-04-02T01:41:43Z","pushed_at":"2015-04-02T18:40:38Z","git_url":"git://github.com/puppetlabs/puppet-server.git","ssh_url":"git@github.com:puppetlabs/puppet-server.git","clone_url":"https://github.com/puppetlabs/puppet-server.git","svn_url":"https://github.com/puppetlabs/puppet-server","homepage":"https://tickets.puppetlabs.com/browse/SERVER","size":6171,"stargazers_count":90,"watchers_count":90,"language":"Clojure","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":47,"mirror_url":null,"open_issues_count":7,"forks":47,"open_issues":7,"watchers":90,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416"},"html":{"href":"https://github.com/puppetlabs/puppet-server/pull/416"},"issue":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/issues/416"},"comments":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/issues/416/comments"},"review_comments":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416/comments"},"review_comment":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/pulls/416/commits"},"statuses":{"href":"https://api.github.com/repos/puppetlabs/puppet-server/statuses/2980a78dbb727dd1916da62568941dfee82206a0"}}}}