From 79d4e7909d4868033d5246c25ded0278be20ee07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:24:10 +0000 Subject: [PATCH 01/62] Bump io.undertow:undertow-core in /frameworks/Java/undertow-jersey Bumps [io.undertow:undertow-core](https://github.com/undertow-io/undertow) from 2.3.12.Final to 2.3.14.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.3.12.Final...2.3.14.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Java/undertow-jersey/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Java/undertow-jersey/pom.xml b/frameworks/Java/undertow-jersey/pom.xml index 5be3dd82456..bf4603735ca 100644 --- a/frameworks/Java/undertow-jersey/pom.xml +++ b/frameworks/Java/undertow-jersey/pom.xml @@ -174,7 +174,7 @@ io.undertow undertow-core - 2.3.12.Final + 2.3.14.Final From 57fa858b659f254acad570464374ed92a9a3c787 Mon Sep 17 00:00:00 2001 From: Fangdun Tsai Date: Sat, 29 Jun 2024 00:21:46 +0800 Subject: [PATCH 02/62] [rust/viz] rust v1.79 (#9131) --- frameworks/Rust/viz/Cargo.toml | 4 ++-- frameworks/Rust/viz/viz-diesel.dockerfile | 2 +- frameworks/Rust/viz/viz-pg.dockerfile | 2 +- frameworks/Rust/viz/viz-sqlx.dockerfile | 2 +- frameworks/Rust/viz/viz.dockerfile | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frameworks/Rust/viz/Cargo.toml b/frameworks/Rust/viz/Cargo.toml index 9832cb58fdb..f28595febb5 100644 --- a/frameworks/Rust/viz/Cargo.toml +++ b/frameworks/Rust/viz/Cargo.toml @@ -42,10 +42,10 @@ sqlx = { version = "0.7", features = [ "runtime-tokio", "tls-native-tls" ], optional = true } -diesel = { version = "2.0", default-features = false, features = [ +diesel = { version = "2.2", default-features = false, features = [ "i-implement-a-third-party-backend-and-opt-into-breaking-changes", ], optional = true } -diesel-async = { version = "0.4", default-features = false, features = [ +diesel-async = { git = "https://github.com/weiznich/diesel_async.git", rev = "74867bd", version = "0.4", default-features = false, features = [ "postgres", "bb8", ], optional = true } diff --git a/frameworks/Rust/viz/viz-diesel.dockerfile b/frameworks/Rust/viz/viz-diesel.dockerfile index c1ddd42ddd5..d37e0af9130 100644 --- a/frameworks/Rust/viz/viz-diesel.dockerfile +++ b/frameworks/Rust/viz/viz-diesel.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.75 +FROM rust:1.79 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/viz/viz-pg.dockerfile b/frameworks/Rust/viz/viz-pg.dockerfile index 69238ff1c62..326f10a3bc6 100644 --- a/frameworks/Rust/viz/viz-pg.dockerfile +++ b/frameworks/Rust/viz/viz-pg.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.75 +FROM rust:1.79 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/viz/viz-sqlx.dockerfile b/frameworks/Rust/viz/viz-sqlx.dockerfile index 087feee3c8e..76104544be0 100644 --- a/frameworks/Rust/viz/viz-sqlx.dockerfile +++ b/frameworks/Rust/viz/viz-sqlx.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.75 +FROM rust:1.79 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/viz/viz.dockerfile b/frameworks/Rust/viz/viz.dockerfile index bf54a7076c9..d6fd457b66e 100644 --- a/frameworks/Rust/viz/viz.dockerfile +++ b/frameworks/Rust/viz/viz.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.75 +FROM rust:1.79 RUN apt-get update -yqq && apt-get install -yqq cmake g++ From 4398d2cad63279a794bb6ce35449b08ce8cf3208 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Fri, 28 Jun 2024 18:21:56 +0200 Subject: [PATCH 03/62] [ruby|rack-sequel] Batch update for Postgres (#9130) Also remove Rack::Chunked middleware as it is no longer supported. --- frameworks/Ruby/rack-sequel/boot.rb | 34 +++++++++++++++++----- frameworks/Ruby/rack-sequel/config.ru | 1 - frameworks/Ruby/rack-sequel/hello_world.rb | 26 ++++++++--------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/frameworks/Ruby/rack-sequel/boot.rb b/frameworks/Ruby/rack-sequel/boot.rb index e4de89199e9..609e3dacceb 100644 --- a/frameworks/Ruby/rack-sequel/boot.rb +++ b/frameworks/Ruby/rack-sequel/boot.rb @@ -33,8 +33,8 @@ def connect(dbtype) Bundler.require(dbtype) # Load database-specific modules adapters = { - :mysql=>{ :jruby=>'jdbc:mysql', :mri=>'mysql2' }, - :postgresql=>{ :jruby=>'jdbc:postgresql', :mri=>'postgres' } + mysql: { jruby: 'jdbc:mysql', mri: 'mysql2' }, + postgresql: { jruby: 'jdbc:postgresql', mri: 'postgres' } } opts = {} @@ -52,11 +52,11 @@ def connect(dbtype) Sequel.connect \ '%{adapter}://%{host}/%{database}?user=%{user}&password=%{password}' % { - :adapter=>adapters.fetch(dbtype).fetch(defined?(JRUBY_VERSION) ? :jruby : :mri), - :host=>'tfb-database', - :database=>'hello_world', - :user=>'benchmarkdbuser', - :password=>'benchmarkdbpass' + adapter: adapters.fetch(dbtype).fetch(defined?(JRUBY_VERSION) ? :jruby : :mri), + host: 'tfb-database', + database: 'hello_world', + user: 'benchmarkdbuser', + password: 'benchmarkdbpass' }, opts end @@ -64,7 +64,27 @@ def connect(dbtype) # Define ORM models class World < Sequel::Model(:World) + BY_ID = naked.where(id: :$id).prepare(:first, :world_by_id) + UPDATE = where(id: :$id).prepare(:update, :world_update, randomnumber: :$randomnumber) + def_column_alias(:randomnumber, :randomNumber) if DB.database_type == :mysql + + def self.batch_update(worlds) + if DB.database_type == :mysql + worlds.each do |world| + UPDATE.(id: world[:id], randomnumber: world[:randomnumber]) + end + else + ids = [] + sql = String.new("UPDATE world SET randomnumber = CASE id ") + worlds.each do |world| + sql << "when #{world[:id]} then #{world[:randomnumber]} " + ids << world[:id] + end + sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})" + DB.run(sql) + end + end end class Fortune < Sequel::Model(:Fortune) diff --git a/frameworks/Ruby/rack-sequel/config.ru b/frameworks/Ruby/rack-sequel/config.ru index ff84c719d0f..8fceb7c06fc 100644 --- a/frameworks/Ruby/rack-sequel/config.ru +++ b/frameworks/Ruby/rack-sequel/config.ru @@ -1,5 +1,4 @@ require_relative 'boot' require_relative 'hello_world' use Rack::ContentLength -use Rack::Chunked run HelloWorld.new diff --git a/frameworks/Ruby/rack-sequel/hello_world.rb b/frameworks/Ruby/rack-sequel/hello_world.rb index 77525d99e45..d68de1f48d7 100644 --- a/frameworks/Ruby/rack-sequel/hello_world.rb +++ b/frameworks/Ruby/rack-sequel/hello_world.rb @@ -20,17 +20,14 @@ def rand1 rand(MAX_PK).succ end - WORLD_BY_ID = World.naked.where(:id=>:$id).prepare(:first, :world_by_id) - WORLD_UPDATE = World.where(:id=>:$id).prepare(:update, :world_update, :randomnumber=>:$randomnumber) - def db - WORLD_BY_ID.(:id=>rand1) + World::BY_ID.(id: rand1) end def queries(env) DB.synchronize do ALL_IDS.sample(bounded_queries(env)).map do |id| - WORLD_BY_ID.(id: id) + World::BY_ID.(id: id) end end end @@ -38,8 +35,8 @@ def queries(env) def fortunes fortunes = Fortune.all fortunes << Fortune.new( - :id=>0, - :message=>'Additional fortune added at request time.' + id: 0, + message: 'Additional fortune added at request time.' ) fortunes.sort_by!(&:message) @@ -78,11 +75,14 @@ def fortunes def updates(env) DB.synchronize do - ALL_IDS.sample(bounded_queries(env)).map do |id| - world = WORLD_BY_ID.(id: id) - WORLD_UPDATE.(id: world[:id], randomnumber: (world[:randomnumber] = rand1)) - world - end + worlds = + ALL_IDS.sample(bounded_queries(env)).map do |id| + world = World::BY_ID.(id: id) + world[:randomnumber] = rand1 + world + end + World.batch_update(worlds) + worlds end end @@ -91,7 +91,7 @@ def call(env) case env['PATH_INFO'] when '/json' # Test type 1: JSON serialization - [JSON_TYPE, JSON.fast_generate(:message=>'Hello, World!')] + [JSON_TYPE, JSON.fast_generate(message: 'Hello, World!')] when '/db' # Test type 2: Single database query [JSON_TYPE, JSON.fast_generate(db)] From 25862b317e175f95f964d38717fd20fb0434f8e0 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Fri, 28 Jun 2024 18:22:07 +0200 Subject: [PATCH 04/62] [ruby/sinatra-sequel] Use batch update for postgres (#9127) --- frameworks/Ruby/sinatra-sequel/boot.rb | 15 +++++++++++++++ frameworks/Ruby/sinatra-sequel/hello_world.rb | 10 ++++++---- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/frameworks/Ruby/sinatra-sequel/boot.rb b/frameworks/Ruby/sinatra-sequel/boot.rb index 44843e48341..b91ea6e1317 100644 --- a/frameworks/Ruby/sinatra-sequel/boot.rb +++ b/frameworks/Ruby/sinatra-sequel/boot.rb @@ -62,6 +62,21 @@ def connect(dbtype) # Define ORM models class World < Sequel::Model(:World) def_column_alias(:randomnumber, :randomNumber) if DB.database_type == :mysql + + def self.batch_update(worlds) + if DB.database_type == :mysql + worlds.map(&:save_changes) + else + ids = [] + sql = String.new("UPDATE world SET randomnumber = CASE id ") + worlds.each do |world| + sql << "when #{world.id} then #{world.randomnumber} " + ids << world.id + end + sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})" + DB.run(sql) + end + end end class Fortune < Sequel::Model(:Fortune) diff --git a/frameworks/Ruby/sinatra-sequel/hello_world.rb b/frameworks/Ruby/sinatra-sequel/hello_world.rb index ccad94b8303..e04d76a077b 100644 --- a/frameworks/Ruby/sinatra-sequel/hello_world.rb +++ b/frameworks/Ruby/sinatra-sequel/hello_world.rb @@ -78,16 +78,18 @@ def rand1 # Test type 5: Database updates get '/updates' do - worlds = - DB.synchronize do + worlds = nil + DB.synchronize do + worlds = ALL_IDS.sample(bounded_queries).map do |id| world = World.with_pk(id) new_value = rand1 new_value = rand1 while new_value == world.randomnumber - world.update(randomnumber: new_value) + world.randomnumber = new_value world end - end + World.batch_update(worlds) + end json worlds.map!(&:values) end From 635f0686cc2a8a1bf549c3b5aeadadb2ac3ac193 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Fri, 28 Jun 2024 18:22:17 +0200 Subject: [PATCH 05/62] [ruby/roda] Use batch update for Roda on postgres (#9126) --- frameworks/Ruby/roda-sequel/boot.rb | 15 +++++++++++++++ frameworks/Ruby/roda-sequel/hello_world.rb | 14 ++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/frameworks/Ruby/roda-sequel/boot.rb b/frameworks/Ruby/roda-sequel/boot.rb index eafc7bd7932..ebeb5a584c4 100644 --- a/frameworks/Ruby/roda-sequel/boot.rb +++ b/frameworks/Ruby/roda-sequel/boot.rb @@ -73,6 +73,21 @@ def connect(dbtype) # Define ORM models class World < Sequel.Model(:World) def_column_alias(:randomnumber, :randomNumber) if DB.database_type == :mysql + + def self.batch_update(worlds) + if DB.database_type == :mysql + worlds.map(&:save_changes) + else + ids = [] + sql = String.new("UPDATE world SET randomnumber = CASE id ") + worlds.each do |world| + sql << "when #{world.id} then #{world.randomnumber} " + ids << world.id + end + sql << "ELSE randomnumber END WHERE id IN ( #{ids.join(',')})" + DB.run(sql) + end + end end class Fortune < Sequel.Model(:Fortune) diff --git a/frameworks/Ruby/roda-sequel/hello_world.rb b/frameworks/Ruby/roda-sequel/hello_world.rb index abd0d5b1487..6a0a43efccb 100644 --- a/frameworks/Ruby/roda-sequel/hello_world.rb +++ b/frameworks/Ruby/roda-sequel/hello_world.rb @@ -58,17 +58,19 @@ def rand1 # Test type 5: Database updates r.is "updates" do response[CONTENT_TYPE] = JSON_TYPE - worlds = - DB.synchronize do + worlds = [] + DB.synchronize do + worlds = ALL_IDS.sample(bounded_queries).map do |id| world = World.with_pk(id) new_value = rand1 new_value = rand1 while new_value == world.randomnumber - world.update(randomnumber: new_value) - world.values + world.randomnumber = new_value + world end - end - worlds.to_json + World.batch_update(worlds) + end + worlds.map(&:values).to_json end # Test type 6: Plaintext From a8f72550a805a22865cd39e725c4241db65b695f Mon Sep 17 00:00:00 2001 From: Anton Kirilov Date: Fri, 28 Jun 2024 17:22:42 +0100 Subject: [PATCH 06/62] H2O: Use prepared statements for the database updates test (#9124) --- frameworks/C/h2o/src/database.c | 10 +- frameworks/C/h2o/src/database.h | 4 +- frameworks/C/h2o/src/handlers/world.c | 175 +++++++++++++++++--------- 3 files changed, 123 insertions(+), 66 deletions(-) diff --git a/frameworks/C/h2o/src/database.c b/frameworks/C/h2o/src/database.c index 9736cb9f2f0..9c5c843150f 100644 --- a/frameworks/C/h2o/src/database.c +++ b/frameworks/C/h2o/src/database.c @@ -56,8 +56,8 @@ typedef struct { typedef struct { list_t l; - const char *name; - const char *query; + char *name; + char *query; } prepared_statement_t; static h2o_socket_t *create_socket(int sd, h2o_loop_t *loop); @@ -713,8 +713,8 @@ void add_prepared_statement(const char *name, const char *query, list_t **prepar memset(p, 0, sizeof(*p)); p->l.next = *prepared_statements; - p->name = name; - p->query = query; + p->name = h2o_strdup(NULL, name, SIZE_MAX).base; + p->query = h2o_strdup(NULL, query, SIZE_MAX).base; *prepared_statements = &p->l; } @@ -791,6 +791,8 @@ void remove_prepared_statements(list_t *prepared_statements) prepared_statements); prepared_statements = prepared_statements->next; + free(p->name); + free(p->query); free(p); } while (prepared_statements); } diff --git a/frameworks/C/h2o/src/database.h b/frameworks/C/h2o/src/database.h index c0c0ca05eda..160e2ea9abc 100644 --- a/frameworks/C/h2o/src/database.h +++ b/frameworks/C/h2o/src/database.h @@ -49,10 +49,10 @@ typedef struct db_query_param_t { on_result_t on_result; void (*on_timeout)(struct db_query_param_t *); const char *command; - const char * const *paramValues; - const int *paramLengths; const int *paramFormats; + const int *paramLengths; const Oid *paramTypes; + const char * const *paramValues; size_t nParams; uint_fast32_t flags; int resultFormat; diff --git a/frameworks/C/h2o/src/handlers/world.c b/frameworks/C/h2o/src/handlers/world.c index 0ee0b29d497..a87ee4c4282 100644 --- a/frameworks/C/h2o/src/handlers/world.c +++ b/frameworks/C/h2o/src/handlers/world.c @@ -57,17 +57,18 @@ // MAX_UPDATE_QUERY_LEN must be updated whenever UPDATE_QUERY_BEGIN, UPDATE_QUERY_ELEM, // UPDATE_QUERY_MIDDLE, UPDATE_QUERY_ELEM2, and UPDATE_QUERY_END are changed. #define UPDATE_QUERY_BEGIN "UPDATE " WORLD_TABLE_NAME " SET randomNumber = CASE id " -#define UPDATE_QUERY_ELEM "WHEN %" PRIu32 " THEN %" PRIu32 " " -#define UPDATE_QUERY_MIDDLE "ELSE randomNumber END WHERE id IN (%" PRIu32 -#define UPDATE_QUERY_ELEM2 ",%" PRIu32 +#define UPDATE_QUERY_ELEM "WHEN $%zu::integer THEN $%zu::integer " +#define UPDATE_QUERY_MIDDLE "ELSE randomNumber END WHERE id IN ($1::integer" +#define UPDATE_QUERY_ELEM2 ",$%zu::integer" #define UPDATE_QUERY_END ");" #define MAX_UPDATE_QUERY_LEN(n) \ (sizeof(UPDATE_QUERY_BEGIN) + sizeof(UPDATE_QUERY_MIDDLE) + \ sizeof(UPDATE_QUERY_END) - 1 - sizeof(UPDATE_QUERY_ELEM2) + \ (n) * (sizeof(UPDATE_QUERY_ELEM) - 1 + sizeof(UPDATE_QUERY_ELEM2) - 1 + \ - 3 * (sizeof(MKSTR(MAX_ID)) - 1) - 3 * (sizeof(PRIu32) - 1) - 3)) + 3 * sizeof(MKSTR(MAX_QUERIES)) - 3 * (sizeof("%zu") - 1))) +#define UPDATE_QUERY_NAME_PREFIX WORLD_TABLE_NAME "Update" #define USE_CACHE 2 #define WORLD_QUERY "SELECT * FROM " WORLD_TABLE_NAME " WHERE id = $1::integer;" @@ -259,11 +260,16 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req) size_t sz = base_size + num_query_in_progress * sizeof(query_param_t); if (do_update) { - const size_t reuse_size = (num_query_in_progress - 1) * sizeof(query_param_t); - const size_t update_query_len = MAX_UPDATE_QUERY_LEN(num_query); + size_t s = base_size + sizeof(query_param_t); - if (update_query_len > reuse_size) - sz += update_query_len - reuse_size; + s = (s + _Alignof(const char *) - 1) / _Alignof(const char *); + s = s * _Alignof(const char *) + 2 * num_query * sizeof(const char *); + s = (s + _Alignof(int) - 1) / _Alignof(int); + s = s * _Alignof(int) + 4 * num_query * sizeof(int); + s += sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES)); + + if (s > sz) + sz = s; } multiple_query_ctx_t * const query_ctx = h2o_mem_alloc(sz); @@ -332,65 +338,57 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req) static void do_updates(multiple_query_ctx_t *query_ctx) { - char *iter = (char *) (query_ctx->query_param + 1); - size_t sz = MAX_UPDATE_QUERY_LEN(query_ctx->num_result); - - // Sort the results to avoid database deadlock. - qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items); - query_ctx->query_param->param.command = iter; - query_ctx->query_param->param.nParams = 0; - query_ctx->query_param->param.on_result = on_update_result; - query_ctx->query_param->param.paramFormats = NULL; - query_ctx->query_param->param.paramLengths = NULL; - query_ctx->query_param->param.paramValues = NULL; - query_ctx->query_param->param.flags = 0; + size_t offset = + offsetof(multiple_query_ctx_t, res) + query_ctx->num_result * sizeof(*query_ctx->res); - int c = snprintf(iter, sz, UPDATE_QUERY_BEGIN); - - if ((size_t) c >= sz) - goto error; - - iter += c; - sz -= c; - - for (size_t i = 0; i < query_ctx->num_result; i++) { - query_ctx->res[i].random_number = 1 + get_random_number(MAX_ID, - &query_ctx->ctx->random_seed); - c = snprintf(iter, - sz, - UPDATE_QUERY_ELEM, - query_ctx->res[i].id, - query_ctx->res[i].random_number); + offset = ((offset + _Alignof(query_param_t) - 1) / _Alignof(query_param_t)); + offset = offset * _Alignof(query_param_t) + sizeof(query_param_t); + offset = (offset + _Alignof(const char *) - 1) / _Alignof(const char *); + offset *= _Alignof(const char *); - if ((size_t) c >= sz) - goto error; + const char ** const paramValues = (const char **) ((char *) query_ctx + offset); + const size_t nParams = query_ctx->num_result * 2; - iter += c; - sz -= c; - } + offset += nParams * sizeof(*paramValues); + offset = (offset + _Alignof(int) - 1) / _Alignof(int); + offset *= _Alignof(int); - c = snprintf(iter, sz, UPDATE_QUERY_MIDDLE, query_ctx->res->id); + int * const paramFormats = (int *) ((char *) query_ctx + offset); + int * const paramLengths = paramFormats + nParams; + char * const command = (char *) (paramLengths + nParams); + const size_t command_size = + sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES)) - sizeof(UPDATE_QUERY_NAME_PREFIX) + 1; + const int c = snprintf(command + sizeof(UPDATE_QUERY_NAME_PREFIX) - 1, + command_size, + "%zu", + query_ctx->num_result); - if ((size_t) c >= sz) + if ((size_t) c >= command_size) goto error; - iter += c; - sz -= c; - - for (size_t i = 1; i < query_ctx->num_result; i++) { - c = snprintf(iter, sz, UPDATE_QUERY_ELEM2, query_ctx->res[i].id); - - if ((size_t) c >= sz) - goto error; - - iter += c; - sz -= c; - } - - c = snprintf(iter, sz, UPDATE_QUERY_END); + memcpy(command, UPDATE_QUERY_NAME_PREFIX, sizeof(UPDATE_QUERY_NAME_PREFIX) - 1); + // Sort the results to avoid database deadlock. + qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items); - if ((size_t) c >= sz) - goto error; + for (size_t i = 0; i < query_ctx->num_result; i++) { + query_ctx->res[i].id = htonl(query_ctx->res[i].id); + query_ctx->res[i].random_number = + htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed)); + paramFormats[2 * i] = 1; + paramFormats[2 * i + 1] = 1; + paramLengths[2 * i] = sizeof(query_ctx->res[i].id); + paramLengths[2 * i + 1] = sizeof(query_ctx->res[i].random_number); + paramValues[2 * i] = (const char *) &query_ctx->res[i].id; + paramValues[2 * i + 1] = (const char *) &query_ctx->res[i].random_number; + } + + query_ctx->query_param->param.command = command; + query_ctx->query_param->param.flags = IS_PREPARED; + query_ctx->query_param->param.nParams = nParams; + query_ctx->query_param->param.on_result = on_update_result; + query_ctx->query_param->param.paramFormats = paramFormats; + query_ctx->query_param->param.paramLengths = paramLengths; + query_ctx->query_param->param.paramValues = paramValues; if (execute_database_query(&query_ctx->ctx->request_handler_data.hello_world_db, &query_ctx->query_param->param)) { @@ -726,8 +724,14 @@ static result_return_t on_update_result(db_query_param_t *param, PGresult *resul query_ctx->gen = get_json_generator(&query_ctx->ctx->json_generator, &query_ctx->ctx->json_generator_num); - if (query_ctx->gen) + if (query_ctx->gen) { + for (size_t i = 0; i < query_ctx->num_result; i++) { + query_ctx->res[i].id = ntohl(query_ctx->res[i].id); + query_ctx->res[i].random_number = ntohl(query_ctx->res[i].random_number); + } + serialize_items(query_ctx->res, query_ctx->num_result, &query_ctx->gen, query_ctx->req); + } else send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req); } @@ -887,6 +891,57 @@ void initialize_world_handlers(h2o_hostconf_t *hostconf, h2o_access_log_filehandle_t *log_handle, request_handler_data_t *data) { + char name[sizeof(UPDATE_QUERY_NAME_PREFIX MKSTR(MAX_QUERIES))]; + char query[MAX_UPDATE_QUERY_LEN(MAX_QUERIES)]; + const size_t name_size = sizeof(name) - sizeof(UPDATE_QUERY_NAME_PREFIX) + 1; + + assert(sizeof(name) >= sizeof(UPDATE_QUERY_NAME_PREFIX)); + memcpy(name, UPDATE_QUERY_NAME_PREFIX, sizeof(UPDATE_QUERY_NAME_PREFIX) - 1); + assert(sizeof(query) >= sizeof(UPDATE_QUERY_BEGIN)); + memcpy(query, UPDATE_QUERY_BEGIN, sizeof(UPDATE_QUERY_BEGIN) - 1); + + for (size_t i = 0; i < MAX_QUERIES; i++) { + char *iter = query + sizeof(UPDATE_QUERY_BEGIN) - 1; + size_t sz = sizeof(query) - sizeof(UPDATE_QUERY_BEGIN) + 1; + int c = snprintf(name + sizeof(UPDATE_QUERY_NAME_PREFIX) - 1, name_size, "%zu", i + 1); + + if ((size_t) c >= name_size) + continue; + + for (size_t j = 0; j <= i; j++) { + c = snprintf(iter, + sz, + UPDATE_QUERY_ELEM, + 2 * j + 1, + 2 * j + 2); + + if ((size_t) c >= sz) + continue; + + iter += c; + sz -= c; + } + + assert(sz >= sizeof(UPDATE_QUERY_MIDDLE)); + memcpy(iter, UPDATE_QUERY_MIDDLE, sizeof(UPDATE_QUERY_MIDDLE) - 1); + iter += sizeof(UPDATE_QUERY_MIDDLE) - 1; + sz -= sizeof(UPDATE_QUERY_MIDDLE) - 1; + + for (size_t j = 1; j <= i; j++) { + c = snprintf(iter, sz, UPDATE_QUERY_ELEM2, 2 * j + 1); + + if ((size_t) c >= sz) + continue; + + iter += c; + sz -= c; + } + + assert(sz >= sizeof(UPDATE_QUERY_END)); + memcpy(iter, UPDATE_QUERY_END, sizeof(UPDATE_QUERY_END)); + add_prepared_statement(name, query, &data->prepared_statements); + } + add_prepared_statement(WORLD_TABLE_NAME, WORLD_QUERY, &data->prepared_statements); register_request_handler("/cached-worlds", cached_queries, hostconf, log_handle); register_request_handler("/db", single_query, hostconf, log_handle); From d1b194430c9d523f034428531d0f0b08ea427d55 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 1 Jul 2024 19:49:42 +0200 Subject: [PATCH 07/62] [rails] Don't bulk update on MySQL (#9122) The benchmarks currently don't take into account batch updates in MySQL. This fixes the flaky MySQL updates verification. --- frameworks/Ruby/rails/app/models/world.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frameworks/Ruby/rails/app/models/world.rb b/frameworks/Ruby/rails/app/models/world.rb index 278501c05f4..bc1c8e9311b 100644 --- a/frameworks/Ruby/rails/app/models/world.rb +++ b/frameworks/Ruby/rails/app/models/world.rb @@ -3,4 +3,14 @@ class World < ApplicationRecord alias_attribute(:randomNumber, :randomnumber) \ if connection.adapter_name.downcase.start_with?('postgres') + + if connection.adapter_name.downcase.start_with?('trilogy') + def self.upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) + # On MySQL Batch updates verification isn't supported yet by TechEmpower. + # https://github.com/TechEmpower/FrameworkBenchmarks/issues/5983 + attributes.each do |attrs| + where(id: attrs[:id]).update_all(randomNumber: attrs[:randomNumber]) + end + end + end end From 7388a89641eeddebcb9aff6a4f8c079fa64ef139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Tue, 2 Jul 2024 01:49:52 +0800 Subject: [PATCH 08/62] [New Framework]: Goravel (#9125) * feat: add goravel test case * feat: optimize code * fix: query with pool --- frameworks/Go/goravel/README.md | 44 + frameworks/Go/goravel/benchmark_config.json | 55 + .../Go/goravel/goravel-fiber.dockerfile | 21 + frameworks/Go/goravel/goravel.dockerfile | 19 + frameworks/Go/goravel/src/fiber/.env | 1 + .../app/http/controllers/test_controller.go | 126 ++ .../src/fiber/app/http/controllers/utils.go | 107 ++ .../Go/goravel/src/fiber/app/models/world.go | 10 + .../app/providers/route_service_provider.go | 16 + frameworks/Go/goravel/src/fiber/config/app.go | 40 + .../Go/goravel/src/fiber/config/cache.go | 18 + .../Go/goravel/src/fiber/config/database.go | 32 + .../Go/goravel/src/fiber/config/http.go | 26 + .../Go/goravel/src/fiber/config/json.go | 31 + frameworks/Go/goravel/src/fiber/go.mod | 191 +++ frameworks/Go/goravel/src/fiber/go.sum | 1170 +++++++++++++++++ frameworks/Go/goravel/src/fiber/main.go | 27 + frameworks/Go/goravel/src/fiber/routes/web.go | 19 + .../Go/goravel/src/fiber/templates/fortune.go | 53 + .../goravel/src/fiber/templates/fortune.qtpl | 15 + .../src/fiber/templates/fortune.qtpl.go | 81 ++ frameworks/Go/goravel/src/gin/.env | 1 + .../app/http/controllers/test_controller.go | 129 ++ .../src/gin/app/http/controllers/utils.go | 101 ++ .../Go/goravel/src/gin/app/models/fortune.go | 10 + .../Go/goravel/src/gin/app/models/world.go | 10 + .../app/providers/route_service_provider.go | 16 + frameworks/Go/goravel/src/gin/config/app.go | 40 + frameworks/Go/goravel/src/gin/config/cache.go | 18 + .../Go/goravel/src/gin/config/database.go | 32 + frameworks/Go/goravel/src/gin/config/http.go | 30 + frameworks/Go/goravel/src/gin/config/json.go | 31 + frameworks/Go/goravel/src/gin/go.mod | 194 +++ frameworks/Go/goravel/src/gin/go.sum | 1170 +++++++++++++++++ frameworks/Go/goravel/src/gin/main.go | 27 + .../src/gin/resources/views/fortunes.tmpl | 22 + frameworks/Go/goravel/src/gin/routes/web.go | 19 + 37 files changed, 3952 insertions(+) create mode 100644 frameworks/Go/goravel/README.md create mode 100644 frameworks/Go/goravel/benchmark_config.json create mode 100644 frameworks/Go/goravel/goravel-fiber.dockerfile create mode 100644 frameworks/Go/goravel/goravel.dockerfile create mode 100644 frameworks/Go/goravel/src/fiber/.env create mode 100644 frameworks/Go/goravel/src/fiber/app/http/controllers/test_controller.go create mode 100644 frameworks/Go/goravel/src/fiber/app/http/controllers/utils.go create mode 100644 frameworks/Go/goravel/src/fiber/app/models/world.go create mode 100644 frameworks/Go/goravel/src/fiber/app/providers/route_service_provider.go create mode 100644 frameworks/Go/goravel/src/fiber/config/app.go create mode 100644 frameworks/Go/goravel/src/fiber/config/cache.go create mode 100644 frameworks/Go/goravel/src/fiber/config/database.go create mode 100644 frameworks/Go/goravel/src/fiber/config/http.go create mode 100644 frameworks/Go/goravel/src/fiber/config/json.go create mode 100644 frameworks/Go/goravel/src/fiber/go.mod create mode 100644 frameworks/Go/goravel/src/fiber/go.sum create mode 100644 frameworks/Go/goravel/src/fiber/main.go create mode 100644 frameworks/Go/goravel/src/fiber/routes/web.go create mode 100644 frameworks/Go/goravel/src/fiber/templates/fortune.go create mode 100644 frameworks/Go/goravel/src/fiber/templates/fortune.qtpl create mode 100644 frameworks/Go/goravel/src/fiber/templates/fortune.qtpl.go create mode 100644 frameworks/Go/goravel/src/gin/.env create mode 100644 frameworks/Go/goravel/src/gin/app/http/controllers/test_controller.go create mode 100644 frameworks/Go/goravel/src/gin/app/http/controllers/utils.go create mode 100644 frameworks/Go/goravel/src/gin/app/models/fortune.go create mode 100644 frameworks/Go/goravel/src/gin/app/models/world.go create mode 100644 frameworks/Go/goravel/src/gin/app/providers/route_service_provider.go create mode 100644 frameworks/Go/goravel/src/gin/config/app.go create mode 100644 frameworks/Go/goravel/src/gin/config/cache.go create mode 100644 frameworks/Go/goravel/src/gin/config/database.go create mode 100644 frameworks/Go/goravel/src/gin/config/http.go create mode 100644 frameworks/Go/goravel/src/gin/config/json.go create mode 100644 frameworks/Go/goravel/src/gin/go.mod create mode 100644 frameworks/Go/goravel/src/gin/go.sum create mode 100644 frameworks/Go/goravel/src/gin/main.go create mode 100644 frameworks/Go/goravel/src/gin/resources/views/fortunes.tmpl create mode 100644 frameworks/Go/goravel/src/gin/routes/web.go diff --git a/frameworks/Go/goravel/README.md b/frameworks/Go/goravel/README.md new file mode 100644 index 00000000000..f9b0d413503 --- /dev/null +++ b/frameworks/Go/goravel/README.md @@ -0,0 +1,44 @@ +# Goravel Benchmarking Test + +[Goravel](https://www.goravel.dev/) is a web application framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + +The framework's design is consistent with [Laravel](https://github.com/laravel/laravel), simplifying the learning curve for PHPers. Kudos to Laravel! + +### Test Type Implementation Source Code + +* [JSON](src/gin/app/http/controllers/test_controller.go) +* [PLAINTEXT](src/gin/app/http/controllers/test_controller.go) +* [DB](src/gin/app/http/controllers/test_controller.go) +* [QUERY](src/gin/app/http/controllers/test_controller.go) +* [CACHED QUERY](src/gin/app/http/controllers/test_controller.go) +* [UPDATE](src/gin/app/http/controllers/test_controller.go) +* [FORTUNES](src/gin/app/http/controllers/test_controller.go) + +## Test URLs +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +### DB + +http://localhost:8080/db + +### QUERY + +http://localhost:8080/query?q= + +### CACHED QUERY + +http://localhost:8080/cached_query?q= + +### UPDATE + +http://localhost:8080/update?q= + +### FORTUNES + +http://localhost:8080/fortunes diff --git a/frameworks/Go/goravel/benchmark_config.json b/frameworks/Go/goravel/benchmark_config.json new file mode 100644 index 00000000000..bcb01875139 --- /dev/null +++ b/frameworks/Go/goravel/benchmark_config.json @@ -0,0 +1,55 @@ +{ + "framework": "goravel", + "tests": [ + { + "default": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?q=", + "fortune_url": "/fortunes", + "cached_query_url": "/cached-worlds?q=", + "update_url": "/update?q=", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "postgres", + "framework": "goravel", + "language": "Go", + "flavor": "None", + "orm": "Full", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Goravel Gin", + "notes": "", + "versus": "go" + }, + "fiber": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?q=", + "fortune_url": "/fortunes", + "cached_query_url": "/cached-worlds?q=", + "update_url": "/update?q=", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "postgres", + "framework": "goravel", + "language": "Go", + "flavor": "None", + "orm": "Full", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Goravel Fiber", + "notes": "", + "versus": "go" + } + } + ] +} diff --git a/frameworks/Go/goravel/goravel-fiber.dockerfile b/frameworks/Go/goravel/goravel-fiber.dockerfile new file mode 100644 index 00000000000..91d583dface --- /dev/null +++ b/frameworks/Go/goravel/goravel-fiber.dockerfile @@ -0,0 +1,21 @@ +FROM golang:1.22-alpine + +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOAMD64=v3 \ + GOARCH="amd64" \ + GOOS=linux + +WORKDIR /go/goravel + +COPY ./src/fiber /go/goravel + +RUN go mod tidy + +RUN go generate -x ./templates + +RUN go build -ldflags '-s -w --extldflags "-static"' -o /go/goravel/main + +EXPOSE 8080 + +CMD /go/goravel/main diff --git a/frameworks/Go/goravel/goravel.dockerfile b/frameworks/Go/goravel/goravel.dockerfile new file mode 100644 index 00000000000..2000cbbcf35 --- /dev/null +++ b/frameworks/Go/goravel/goravel.dockerfile @@ -0,0 +1,19 @@ +FROM golang:1.22-alpine + +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOAMD64=v3 \ + GOARCH="amd64" \ + GOOS=linux + +WORKDIR /go/goravel + +COPY ./src/gin /go/goravel + +RUN go mod tidy + +RUN go build -tags="sonic avx" -ldflags '-s -w --extldflags "-static"' -o /go/goravel/main + +EXPOSE 8080 + +CMD /go/goravel/main diff --git a/frameworks/Go/goravel/src/fiber/.env b/frameworks/Go/goravel/src/fiber/.env new file mode 100644 index 00000000000..9ceb9e63dc9 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/.env @@ -0,0 +1 @@ +APP_KEY=abcdefghijklmnopqrstuvwxyz123456 \ No newline at end of file diff --git a/frameworks/Go/goravel/src/fiber/app/http/controllers/test_controller.go b/frameworks/Go/goravel/src/fiber/app/http/controllers/test_controller.go new file mode 100644 index 00000000000..c433f221e7b --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/app/http/controllers/test_controller.go @@ -0,0 +1,126 @@ +package controllers + +import ( + "math/rand/v2" + "sort" + + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/facades" + + "goravel/templates" +) + +type TestController struct{} + +func NewTestController() *TestController { + initCache() + return &TestController{} +} + +func (r *TestController) Plaintext(ctx http.Context) http.Response { + Plaintext(ctx, helloworld) + return nil +} + +func (r *TestController) JSON(ctx http.Context) http.Response { + message := acquireMessage() + message.Message = helloworld + + JSON(ctx, &message) + releaseMessage(message) + return nil +} + +func (r *TestController) DB(ctx http.Context) http.Response { + world := acquireWorld() + + world.ID = r.getRand() + _ = facades.Orm().Query().Find(&world) + + JSON(ctx, &world) + releaseWorld(world) + return nil +} + +func (r *TestController) Queries(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + + for i := 0; i < n; i++ { + worlds[i].ID = r.getRand() + _ = facades.Orm().Query().Find(&worlds[i]) + } + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) Update(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + + for i := 0; i < n; i++ { + worlds[i].ID = r.getRand() + _ = facades.Orm().Query().Find(&worlds[i]) + } + + // sorting is required for insert deadlock prevention. + sort.Slice(worlds, func(i, j int) bool { + return worlds[i].ID < worlds[j].ID + }) + + tx, _ := facades.Orm().Query().Begin() + for i := 0; i < n; i++ { + worlds[i].RandomNumber = r.getRand() + _ = tx.Save(&worlds[i]) + } + _ = tx.Commit() + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) Fortunes(ctx http.Context) http.Response { + fortunes := make([]templates.Fortune, 0) + _ = facades.Orm().Query().Table("Fortune").Get(&fortunes) + + fortunes = append(fortunes, templates.Fortune{Message: "Additional fortune added at request time."}) + sort.Slice(fortunes, func(i, j int) bool { + return fortunes[i].Message < fortunes[j].Message + }) + + HTML(ctx) + templates.WriteFortunePage(ctx.Response().Writer(), fortunes) + return nil +} + +func (r *TestController) CacheQueries(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + cached := facades.Cache().Get("worlds").(Worlds) + + for i := 0; i < n; i++ { + worlds[i] = cached[r.getRand()-1] + } + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) getN(ctx http.Context) int { + n := ctx.Request().QueryInt(queryparam) + if n < 1 { + n = 1 + } else if n > 500 { + n = 500 + } + + return n +} + +func (r *TestController) getRand() int32 { + return rand.Int32N(worldcount) + 1 +} diff --git a/frameworks/Go/goravel/src/fiber/app/http/controllers/utils.go b/frameworks/Go/goravel/src/fiber/app/http/controllers/utils.go new file mode 100644 index 00000000000..b125edad3f3 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/app/http/controllers/utils.go @@ -0,0 +1,107 @@ +package controllers + +import ( + "fmt" + "sync" + "unsafe" + + "github.com/bytedance/sonic" + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/facades" + + "goravel/app/models" +) + +const ( + queryparam = "q" + helloworld = "Hello, World!" + worldcount = 10000 + contentTypePlain = "text/plain; charset=utf-8" + contentTypeHtml = "text/html; charset=utf-8" + contentTypeJson = "application/json" +) + +type Message struct { + Message string `json:"message"` +} + +type Worlds []models.World + +var messagePool = sync.Pool{ + New: func() any { + return new(Message) + }, +} + +var worldPool = sync.Pool{ + New: func() any { + return new(models.World) + }, +} + +var worldsPool = sync.Pool{ + New: func() any { + return make(Worlds, 0, 500) + }, +} + +func acquireMessage() *Message { + return messagePool.Get().(*Message) +} + +func releaseMessage(m *Message) { + m.Message = "" + messagePool.Put(m) +} + +func acquireWorld() *models.World { + return worldPool.Get().(*models.World) +} + +func releaseWorld(w *models.World) { + w.ID = 0 + w.RandomNumber = 0 + worldPool.Put(w) +} + +func acquireWorlds() Worlds { + return worldsPool.Get().(Worlds) +} + +func releaseWorlds(w Worlds) { + w = w[:0] + worldsPool.Put(w) +} + +func str2bytes(s string) []byte { + return unsafe.Slice(unsafe.StringData(s), len(s)) +} + +func initCache() { + worlds := acquireWorlds() + defer releaseWorlds(worlds) + + if err := facades.Orm().Query().Get(&worlds); err != nil { + panic(fmt.Sprintf("Failed to init cached Worlds: %v", err)) + } + + facades.Cache().Forever("worlds", worlds) +} + +func JSON(ctx http.Context, data any) { + ctx.Response().Header("Server", "Goravel") + ctx.Response().Header("Content-Type", contentTypeJson) + bytes, _ := sonic.Marshal(data) + _, _ = ctx.Response().Writer().Write(bytes) +} + +func Plaintext(ctx http.Context, data string) { + ctx.Response().Header("Server", "Goravel") + ctx.Response().Header("Content-Type", contentTypePlain) + _, _ = ctx.Response().Writer().Write(str2bytes(data)) +} + +func HTML(ctx http.Context) { + ctx.Response().Header("Server", "Goravel") + ctx.Response().Header("Content-Type", contentTypeHtml) +} diff --git a/frameworks/Go/goravel/src/fiber/app/models/world.go b/frameworks/Go/goravel/src/fiber/app/models/world.go new file mode 100644 index 00000000000..da724366273 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/app/models/world.go @@ -0,0 +1,10 @@ +package models + +type World struct { + ID int32 `gorm:"primaryKey" json:"id"` + RandomNumber int32 `gorm:"column:randomnumber" json:"randomNumber"` +} + +func (r *World) TableName() string { + return "World" +} diff --git a/frameworks/Go/goravel/src/fiber/app/providers/route_service_provider.go b/frameworks/Go/goravel/src/fiber/app/providers/route_service_provider.go new file mode 100644 index 00000000000..2e96015a24f --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/app/providers/route_service_provider.go @@ -0,0 +1,16 @@ +package providers + +import ( + "github.com/goravel/framework/contracts/foundation" + + "goravel/routes" +) + +type RouteServiceProvider struct{} + +func (receiver *RouteServiceProvider) Register(app foundation.Application) { +} + +func (receiver *RouteServiceProvider) Boot(app foundation.Application) { + routes.Web() +} diff --git a/frameworks/Go/goravel/src/fiber/config/app.go b/frameworks/Go/goravel/src/fiber/config/app.go new file mode 100644 index 00000000000..3ab05123159 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/config/app.go @@ -0,0 +1,40 @@ +package config + +import ( + "github.com/goravel/fiber" + "github.com/goravel/framework/cache" + "github.com/goravel/framework/console" + "github.com/goravel/framework/contracts/foundation" + "github.com/goravel/framework/database" + "github.com/goravel/framework/facades" + "github.com/goravel/framework/http" + "github.com/goravel/framework/log" + "github.com/goravel/framework/route" + "github.com/goravel/framework/validation" + + "goravel/app/providers" +) + +// Boot Start all init methods of the current folder to bootstrap all config. +func Boot() {} + +func init() { + config := facades.Config() + config.Add("app", map[string]any{ + "name": "Goravel", + "env": "production", + "debug": false, + "key": config.Env("APP_KEY", ""), + "providers": []foundation.ServiceProvider{ + &log.ServiceProvider{}, + &console.ServiceProvider{}, + &database.ServiceProvider{}, + &cache.ServiceProvider{}, + &http.ServiceProvider{}, + &route.ServiceProvider{}, + &validation.ServiceProvider{}, + &providers.RouteServiceProvider{}, + &fiber.ServiceProvider{}, + }, + }) +} diff --git a/frameworks/Go/goravel/src/fiber/config/cache.go b/frameworks/Go/goravel/src/fiber/config/cache.go new file mode 100644 index 00000000000..3c638243c2c --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/config/cache.go @@ -0,0 +1,18 @@ +package config + +import ( + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("cache", map[string]any{ + "default": "memory", + "stores": map[string]any{ + "memory": map[string]any{ + "driver": "memory", + }, + }, + "prefix": "goravel_cache", + }) +} diff --git a/frameworks/Go/goravel/src/fiber/config/database.go b/frameworks/Go/goravel/src/fiber/config/database.go new file mode 100644 index 00000000000..e1b1eb3272a --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/config/database.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("database", map[string]any{ + "default": "postgresql", + "connections": map[string]any{ + "postgresql": map[string]any{ + "driver": "postgresql", + "host": config.Env("DB_HOST", "tfb-database"), + "port": config.Env("DB_PORT", 5432), + "database": config.Env("DB_DATABASE", "hello_world"), + "username": config.Env("DB_USERNAME", "benchmarkdbuser"), + "password": config.Env("DB_PASSWORD", "benchmarkdbpass"), + "sslmode": "disable", + "timezone": "UTC", + "prefix": "", + "singular": true, + }, + }, + "pool": map[string]any{ + "max_idle_conns": 100, + "max_open_conns": 2000, + "conn_max_idletime": 3600, + "conn_max_lifetime": 3600, + }, + }) +} diff --git a/frameworks/Go/goravel/src/fiber/config/http.go b/frameworks/Go/goravel/src/fiber/config/http.go new file mode 100644 index 00000000000..3d48d689691 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/config/http.go @@ -0,0 +1,26 @@ +package config + +import ( + fiberfacades "github.com/goravel/fiber/facades" + "github.com/goravel/framework/contracts/route" + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("http", map[string]any{ + "default": "fiber", + "drivers": map[string]any{ + "fiber": map[string]any{ + "prefork": true, + "body_limit": 4096, + "header_limit": 4096, + "route": func() (route.Route, error) { + return fiberfacades.Route("fiber"), nil + }, + }, + }, + "host": "", + "port": "8080", + }) +} diff --git a/frameworks/Go/goravel/src/fiber/config/json.go b/frameworks/Go/goravel/src/fiber/config/json.go new file mode 100644 index 00000000000..2b2e1af3f80 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/config/json.go @@ -0,0 +1,31 @@ +package config + +import ( + "github.com/bytedance/sonic" + "github.com/goravel/framework/contracts/foundation" + "github.com/goravel/framework/facades" +) + +func init() { + facades.App().SetJson(NewJson()) +} + +type Json struct { + marshal func(any) ([]byte, error) + unmarshal func([]byte, any) error +} + +func NewJson() foundation.Json { + return &Json{ + marshal: sonic.Marshal, + unmarshal: sonic.Unmarshal, + } +} + +func (j *Json) Marshal(v any) ([]byte, error) { + return j.marshal(v) +} + +func (j *Json) Unmarshal(data []byte, v any) error { + return j.unmarshal(data, v) +} diff --git a/frameworks/Go/goravel/src/fiber/go.mod b/frameworks/Go/goravel/src/fiber/go.mod new file mode 100644 index 00000000000..e285c0106e3 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/go.mod @@ -0,0 +1,191 @@ +module goravel + +go 1.22 + +require ( + github.com/bytedance/sonic v1.11.9 + github.com/gofiber/fiber/v2 v2.52.4 + github.com/gofiber/template/html/v2 v2.1.1 + github.com/goravel/fiber v1.2.1 + github.com/goravel/framework v1.14.1 + github.com/valyala/quicktemplate v1.7.0 +) + +require ( + atomicgo.dev/cursor v0.2.0 // indirect + atomicgo.dev/keyboard v0.2.9 // indirect + atomicgo.dev/schedule v0.1.0 // indirect + cloud.google.com/go v0.112.1 // indirect + cloud.google.com/go/compute v1.25.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/pubsub v1.36.1 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect + github.com/RichardKnop/machinery/v2 v2.0.13 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aws/aws-sdk-go v1.49.6 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/catppuccin/go v0.2.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charmbracelet/bubbles v0.18.0 // indirect + github.com/charmbracelet/bubbletea v0.26.3 // indirect + github.com/charmbracelet/huh v0.4.2 // indirect + github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0 // indirect + github.com/charmbracelet/lipgloss v0.11.0 // indirect + github.com/charmbracelet/x/ansi v0.1.1 // indirect + github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a // indirect + github.com/charmbracelet/x/input v0.1.1 // indirect + github.com/charmbracelet/x/term v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.1.2 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.4 // indirect + github.com/glebarez/go-sqlite v1.22.0 // indirect + github.com/glebarez/sqlite v1.11.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-redsync/redsync/v4 v4.8.1 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/gofiber/template v1.8.3 // indirect + github.com/gofiber/utils v1.1.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-migrate/migrate/v4 v4.17.1 // indirect + github.com/golang-module/carbon/v2 v2.3.12 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomodule/redigo v2.0.0+incompatible // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/google/wire v0.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.3 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/gookit/filter v1.2.1 // indirect + github.com/gookit/goutil v0.6.15 // indirect + github.com/gookit/validate v1.5.2 // indirect + github.com/goravel/file-rotatelogs/v2 v2.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.5.4 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/microsoft/go-mssqldb v1.6.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.15.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pterm/pterm v0.12.79 // indirect + github.com/rabbitmq/amqp091-go v1.9.0 // indirect + github.com/redis/go-redis/v9 v9.5.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rotisserie/eris v0.5.4 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/savioxavier/termlink v1.3.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/urfave/cli/v2 v2.27.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.55.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.1 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + go.mongodb.org/mongo-driver v1.7.5 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.171.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/grpc v1.64.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.6 // indirect + gorm.io/driver/postgres v1.5.7 // indirect + gorm.io/driver/sqlserver v1.5.3 // indirect + gorm.io/gorm v1.25.10 // indirect + gorm.io/plugin/dbresolver v1.5.1 // indirect + modernc.org/libc v1.37.6 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect + modernc.org/sqlite v1.28.0 // indirect +) diff --git a/frameworks/Go/goravel/src/fiber/go.sum b/frameworks/Go/goravel/src/fiber/go.sum new file mode 100644 index 00000000000..942ea9c3e7f --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/go.sum @@ -0,0 +1,1170 @@ +atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= +atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= +atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= +atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= +atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= +atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= +atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= +atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM= +cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.10.0/go.mod h1:eNpTrkOy7dCpkNyaSNetMa6udbgecJMd0ZsTJS/cuNo= +cloud.google.com/go/pubsub v1.36.1 h1:dfEPuGCHGbWUhaMCTHUFjfroILEkx55iUmKBZTP5f+Y= +cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest/adal v0.9.16 h1:P8An8Z9rH1ldbOLdFpxYorgOt2sywL9V24dAwWHPuGc= +github.com/Azure/go-autorest/autorest/adal v0.9.16/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= +github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= +github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9Ct2d6sC7ol0/ynxc2pO1cpGUM+f4t5adg= +github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU= +github.com/RichardKnop/machinery/v2 v2.0.13 h1:uo9htg+qNBi7UeUK3jcTBl3vTO/vvLKGaOdCOKePl50= +github.com/RichardKnop/machinery/v2 v2.0.13/go.mod h1:Yc2X/QRm9rRfAjB+93NGR+kSUqtnqqs8kME4L+TKKiw= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= +github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/aws/aws-sdk-go v1.37.16/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA= +github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= +github.com/bsm/ginkgo/v2 v2.5.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.20.0/go.mod h1:JifAceMQ4crZIWYUKrlGcmbN3bqHogVTADMD2ATsbwk= +github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg= +github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= +github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= +github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= +github.com/charmbracelet/bubbletea v0.26.3 h1:iXyGvI+FfOWqkB2V07m1DF3xxQijxjY2j8PqiXYqasg= +github.com/charmbracelet/bubbletea v0.26.3/go.mod h1:bpZHfDHTYJC5g+FBK+ptJRCQotRC+Dhh3AoMxa/2+3Q= +github.com/charmbracelet/huh v0.4.2 h1:5wLkwrA58XDAfEZsJzNQlfJ+K8N9+wYwvR5FOM7jXFM= +github.com/charmbracelet/huh v0.4.2/go.mod h1:g9OXBgtY3zRV4ahnVih9bZE+1yGYN+y2C9Q6L2P+WM0= +github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0 h1:79JTuYRirtyCn9ac6rzPt5AQKtBDFc1gKxpw0wBrI+Y= +github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0/go.mod h1:Zxt9FH6togK9kY71pRJGtmyNkJ1eIWdK1gRaXrS/FKA= +github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= +github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= +github.com/charmbracelet/x/ansi v0.1.1 h1:CGAduulr6egay/YVbGc8Hsu8deMg1xZ/bkaXTPi1JDk= +github.com/charmbracelet/x/ansi v0.1.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a h1:lOpqe2UvPmlln41DGoii7wlSZ/q8qGIon5JJ8Biu46I= +github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= +github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a h1:k/s6UoOSVynWiw7PlclyGO2VdVs5ZLbMIHiGp4shFZE= +github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a/go.mod h1:YBotIGhfoWhHDlnUpJMkjebGV2pdGRCn1Y4/Nk/vVcU= +github.com/charmbracelet/x/input v0.1.1 h1:YDOJaTUKCqtGnq9PHzx3pkkl4pXDOANUHmhH3DqMtM4= +github.com/charmbracelet/x/input v0.1.1/go.mod h1:jvdTVUnNWj/RD6hjC4FsoB0SeZCJ2ZBkiuFP9zXvZI0= +github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= +github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= +github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelhxojXlRWg= +github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg= +github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= +github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= +github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= +github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= +github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-redsync/redsync/v4 v4.8.1 h1:rq2RvdTI0obznMdxKUWGdmmulo7lS9yCzb8fgDKOlbM= +github.com/go-redsync/redsync/v4 v4.8.1/go.mod h1:LmUAsQuQxhzZAoGY7JS6+dNhNmZyonMZiiEDY9plotM= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM= +github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc= +github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= +github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8= +github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0= +github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= +github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= +github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= +github.com/golang-module/carbon/v2 v2.3.12 h1:VC1DwN1kBwJkh5MjXmTFryjs5g4CWyoM8HAHffZPX/k= +github.com/golang-module/carbon/v2 v2.3.12/go.mod h1:HNsedGzXGuNciZImYP2OMnpiwq/vhIstR/vn45ib5cI= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= +github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/filter v1.2.1 h1:37XivkBm2E5qe1KaGdJ5ZfF5l9NYdGWfLEeQadJD8O4= +github.com/gookit/filter v1.2.1/go.mod h1:rxynQFr793x+XDwnRmJFEb53zDw0Zqx3OD7TXWoR9mQ= +github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo= +github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY= +github.com/gookit/validate v1.5.2 h1:i5I2OQ7WYHFRPRATGu9QarR9snnNHydvwSuHXaRWAV0= +github.com/gookit/validate v1.5.2/go.mod h1:yuPy2WwDlwGRa06fFJ5XIO8QEwhRnTC2LmxmBa5SE14= +github.com/goravel/fiber v1.2.1 h1:+hVmrxDzbT1bF/9bIgYytnROTgF1u+xgiVGM3N0S1E4= +github.com/goravel/fiber v1.2.1/go.mod h1:DB4QvgQ/WBqgXGs1cemhqAHFvj7jtI/Irk0RhHBWKoQ= +github.com/goravel/file-rotatelogs/v2 v2.4.2 h1:g68AzbePXcm0V2CpUMc9j4qVzcDn7+7aoWSjZ51C0m4= +github.com/goravel/file-rotatelogs/v2 v2.4.2/go.mod h1:23VuSW8cBS4ax5cmbV+5AaiLpq25b8UJ96IhbAkdo8I= +github.com/goravel/framework v1.14.1 h1:VcJvzn1ItFQh/rQZO1EMkxKmzDrww1S+OGz4hjZi3UY= +github.com/goravel/framework v1.14.1/go.mod h1:rScDXGQZdoVfyxemNPmijlz/2a+lWNOa4jTuak5GGVg= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= +github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= +github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= +github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= +github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4= +github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo= +github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc3Aoo= +github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU= +github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo= +github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk= +github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/savioxavier/termlink v1.3.0 h1:3Gl4FzQjUyiHzmoEDfmWEhgIwDiJY4poOQHP+k8ReA4= +github.com/savioxavier/termlink v1.3.0/go.mod h1:5T5ePUlWbxCHIwyF8/Ez1qufOoGM89RCg9NvG+3G3gc= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= +github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8= +github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM= +github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8= +go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M= +go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.7.5 h1:ny3p0reEpgsR2cfA5cjgwFZg3Cv/ofFh/8jbhGtz9VI= +go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.39.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU= +google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8= +gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0= +gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/plugin/dbresolver v1.5.1 h1:s9Dj9f7r+1rE3nx/Ywzc85nXptUEaeOO0pt27xdopM8= +gorm.io/plugin/dbresolver v1.5.1/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= +modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/frameworks/Go/goravel/src/fiber/main.go b/frameworks/Go/goravel/src/fiber/main.go new file mode 100644 index 00000000000..ddd89a4e1a1 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/goravel/framework/facades" + "github.com/goravel/framework/foundation" + + "goravel/config" +) + +func main() { + app := foundation.NewApplication() + + // Bootstrap the application + app.Boot() + + // Bootstrap the config. + config.Boot() + + // Start HTTP server by facades.Route(). + go func() { + if err := facades.Route().Run(); err != nil { + facades.Log().Errorf("Route run error: %v", err) + } + }() + + select {} +} diff --git a/frameworks/Go/goravel/src/fiber/routes/web.go b/frameworks/Go/goravel/src/fiber/routes/web.go new file mode 100644 index 00000000000..86bfbccc2d4 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/routes/web.go @@ -0,0 +1,19 @@ +package routes + +import ( + "github.com/goravel/framework/facades" + + "goravel/app/http/controllers" +) + +func Web() { + testController := controllers.NewTestController() + facades.Route().Get("/plaintext", testController.Plaintext) + facades.Route().Get("/json", testController.JSON) + facades.Route().Get("/db", testController.DB) + facades.Route().Get("/queries", testController.Queries) + facades.Route().Get("/update", testController.Update) + facades.Route().Get("/fortunes", testController.Fortunes) + facades.Route().Get("/cached-worlds", testController.CacheQueries) + +} diff --git a/frameworks/Go/goravel/src/fiber/templates/fortune.go b/frameworks/Go/goravel/src/fiber/templates/fortune.go new file mode 100644 index 00000000000..1d41ca2c80d --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/templates/fortune.go @@ -0,0 +1,53 @@ +package templates + +import ( + "sync" +) + +type Fortune struct { + ID int `json:"id,omitempty"` + Message string `json:"message,omitempty"` +} + +type Fortunes struct { + F []Fortune +} + +//go:generate go run github.com/valyala/quicktemplate/qtc + +var fortunePool = &sync.Pool{ + New: func() interface{} { + return new(Fortune) + }, +} + +var fortunesPool = &sync.Pool{ + New: func() interface{} { + return &Fortunes{ + F: make([]Fortune, 0), + } + }, +} + +// AcquireFortune returns new message from pool. +func AcquireFortune() *Fortune { + return fortunePool.Get().(*Fortune) +} + +// ReleaseFortune resets the message and return it to the pool. +func ReleaseFortune(f *Fortune) { + f.ID = 0 + f.Message = "" + fortunePool.Put(f) +} + +// AcquireFortunes returns new fortunes from pool. +func AcquireFortunes() *Fortunes { + return fortunesPool.Get().(*Fortunes) +} + +// ReleaseFortunes resets the fortunes and return it to the pool. +func ReleaseFortunes(f *Fortunes) { + f.F = f.F[:0] + fortunesPool.Put(f) +} diff --git a/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl b/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl new file mode 100644 index 00000000000..d387990d4ae --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl @@ -0,0 +1,15 @@ +{% func FortunePage(rows []Fortune) %} + + +Fortunes + + + + +{% for _, r := range rows %} + +{% endfor %} +
idmessage
{%d int(r.ID) %}{%s r.Message %}
+ + +{% endfunc %} diff --git a/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl.go b/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl.go new file mode 100644 index 00000000000..8af0bbf4f10 --- /dev/null +++ b/frameworks/Go/goravel/src/fiber/templates/fortune.qtpl.go @@ -0,0 +1,81 @@ +// Code generated by qtc from "fortune.qtpl". DO NOT EDIT. +// See https://github.com/valyala/quicktemplate for details. + +//line fortune.qtpl:1 +package templates + +//line fortune.qtpl:1 +import ( + qtio422016 "io" + + qt422016 "github.com/valyala/quicktemplate" +) + +//line fortune.qtpl:1 +var ( + _ = qtio422016.Copy + _ = qt422016.AcquireByteBuffer +) + +//line fortune.qtpl:1 +func StreamFortunePage(qw422016 *qt422016.Writer, rows []Fortune) { +//line fortune.qtpl:1 + qw422016.N().S(` + + +Fortunes + + + + +`) +//line fortune.qtpl:9 + for _, r := range rows { +//line fortune.qtpl:9 + qw422016.N().S(` + +`) +//line fortune.qtpl:11 + } +//line fortune.qtpl:11 + qw422016.N().S(` +
idmessage
`) +//line fortune.qtpl:10 + qw422016.N().D(int(r.ID)) +//line fortune.qtpl:10 + qw422016.N().S(``) +//line fortune.qtpl:10 + qw422016.E().S(r.Message) +//line fortune.qtpl:10 + qw422016.N().S(`
+ + +`) +//line fortune.qtpl:15 +} + +//line fortune.qtpl:15 +func WriteFortunePage(qq422016 qtio422016.Writer, rows []Fortune) { +//line fortune.qtpl:15 + qw422016 := qt422016.AcquireWriter(qq422016) +//line fortune.qtpl:15 + StreamFortunePage(qw422016, rows) +//line fortune.qtpl:15 + qt422016.ReleaseWriter(qw422016) +//line fortune.qtpl:15 +} + +//line fortune.qtpl:15 +func FortunePage(rows []Fortune) string { +//line fortune.qtpl:15 + qb422016 := qt422016.AcquireByteBuffer() +//line fortune.qtpl:15 + WriteFortunePage(qb422016, rows) +//line fortune.qtpl:15 + qs422016 := string(qb422016.B) +//line fortune.qtpl:15 + qt422016.ReleaseByteBuffer(qb422016) +//line fortune.qtpl:15 + return qs422016 +//line fortune.qtpl:15 +} diff --git a/frameworks/Go/goravel/src/gin/.env b/frameworks/Go/goravel/src/gin/.env new file mode 100644 index 00000000000..9ceb9e63dc9 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/.env @@ -0,0 +1 @@ +APP_KEY=abcdefghijklmnopqrstuvwxyz123456 \ No newline at end of file diff --git a/frameworks/Go/goravel/src/gin/app/http/controllers/test_controller.go b/frameworks/Go/goravel/src/gin/app/http/controllers/test_controller.go new file mode 100644 index 00000000000..7b68b61daeb --- /dev/null +++ b/frameworks/Go/goravel/src/gin/app/http/controllers/test_controller.go @@ -0,0 +1,129 @@ +package controllers + +import ( + "math/rand/v2" + "sort" + + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/facades" + + "goravel/app/models" +) + +type TestController struct{} + +func NewTestController() *TestController { + initCache() + return &TestController{} +} + +func (r *TestController) Plaintext(ctx http.Context) http.Response { + Plaintext(ctx, helloworld) + return nil +} + +func (r *TestController) JSON(ctx http.Context) http.Response { + message := acquireMessage() + message.Message = helloworld + + JSON(ctx, &message) + releaseMessage(message) + return nil +} + +func (r *TestController) DB(ctx http.Context) http.Response { + world := acquireWorld() + + world.ID = r.getRand() + _ = facades.Orm().Query().Find(&world) + + JSON(ctx, &world) + releaseWorld(world) + return nil +} + +func (r *TestController) Queries(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + + for i := 0; i < n; i++ { + worlds[i].ID = r.getRand() + _ = facades.Orm().Query().Find(&worlds[i]) + } + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) Update(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + + for i := 0; i < n; i++ { + worlds[i].ID = r.getRand() + _ = facades.Orm().Query().Find(&worlds[i]) + } + + // sorting is required for insert deadlock prevention. + sort.Slice(worlds, func(i, j int) bool { + return worlds[i].ID < worlds[j].ID + }) + + tx, _ := facades.Orm().Query().Begin() + for i := 0; i < n; i++ { + worlds[i].RandomNumber = r.getRand() + _ = tx.Save(&worlds[i]) + } + _ = tx.Commit() + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) Fortunes(ctx http.Context) http.Response { + fortunes := make([]models.Fortune, 0) + _ = facades.Orm().Query().Get(&fortunes) + fortunes = append(fortunes, models.Fortune{Message: "Additional fortune added at request time."}) + + sort.Slice(fortunes, func(i, j int) bool { + return fortunes[i].Message < fortunes[j].Message + }) + + return ctx.Response(). + Header("Server", "Goravel"). + View(). + Make("fortunes.tmpl", map[string]any{ + "fortunes": fortunes, + }) +} + +func (r *TestController) CacheQueries(ctx http.Context) http.Response { + n := r.getN(ctx) + worlds := acquireWorlds()[:n] + cached := facades.Cache().Get("worlds").(Worlds) + + for i := 0; i < n; i++ { + worlds[i] = cached[r.getRand()-1] + } + + JSON(ctx, &worlds) + releaseWorlds(worlds) + return nil +} + +func (r *TestController) getN(ctx http.Context) int { + n := ctx.Request().QueryInt(queryparam) + if n < 1 { + n = 1 + } else if n > 500 { + n = 500 + } + + return n +} + +func (r *TestController) getRand() int32 { + return rand.Int32N(worldcount) + 1 +} diff --git a/frameworks/Go/goravel/src/gin/app/http/controllers/utils.go b/frameworks/Go/goravel/src/gin/app/http/controllers/utils.go new file mode 100644 index 00000000000..9cac0d34b48 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/app/http/controllers/utils.go @@ -0,0 +1,101 @@ +package controllers + +import ( + "fmt" + "sync" + "unsafe" + + "github.com/bytedance/sonic" + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/facades" + + "goravel/app/models" +) + +const ( + queryparam = "q" + helloworld = "Hello, World!" + worldcount = 10000 + contentTypePlain = "text/plain; charset=utf-8" + contentTypeJson = "application/json" +) + +type Message struct { + Message string `json:"message"` +} + +type Worlds []models.World + +var messagePool = sync.Pool{ + New: func() any { + return new(Message) + }, +} + +var worldPool = sync.Pool{ + New: func() any { + return new(models.World) + }, +} + +var worldsPool = sync.Pool{ + New: func() any { + return make(Worlds, 0, 500) + }, +} + +func acquireMessage() *Message { + return messagePool.Get().(*Message) +} + +func releaseMessage(m *Message) { + m.Message = "" + messagePool.Put(m) +} + +func acquireWorld() *models.World { + return worldPool.Get().(*models.World) +} + +func releaseWorld(w *models.World) { + w.ID = 0 + w.RandomNumber = 0 + worldPool.Put(w) +} + +func acquireWorlds() Worlds { + return worldsPool.Get().(Worlds) +} + +func releaseWorlds(w Worlds) { + w = w[:0] + worldsPool.Put(w) +} + +func str2bytes(s string) []byte { + return unsafe.Slice(unsafe.StringData(s), len(s)) +} + +func initCache() { + worlds := acquireWorlds() + defer releaseWorlds(worlds) + + if err := facades.Orm().Query().Get(&worlds); err != nil { + panic(fmt.Sprintf("Failed to init cached Worlds: %v", err)) + } + + facades.Cache().Forever("worlds", worlds) +} + +func JSON(ctx http.Context, data any) { + ctx.Response().Header("Server", "Goravel") + ctx.Response().Header("Content-Type", contentTypeJson) + bytes, _ := sonic.Marshal(data) + _, _ = ctx.Response().Writer().Write(bytes) +} + +func Plaintext(ctx http.Context, data string) { + ctx.Response().Header("Server", "Goravel") + ctx.Response().Header("Content-Type", contentTypePlain) + _, _ = ctx.Response().Writer().Write(str2bytes(data)) +} diff --git a/frameworks/Go/goravel/src/gin/app/models/fortune.go b/frameworks/Go/goravel/src/gin/app/models/fortune.go new file mode 100644 index 00000000000..8e8e1dd21a8 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/app/models/fortune.go @@ -0,0 +1,10 @@ +package models + +type Fortune struct { + ID uint `gorm:"primaryKey" json:"id"` + Message string `gorm:"column:message" json:"message"` +} + +func (r *Fortune) TableName() string { + return "Fortune" +} diff --git a/frameworks/Go/goravel/src/gin/app/models/world.go b/frameworks/Go/goravel/src/gin/app/models/world.go new file mode 100644 index 00000000000..da724366273 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/app/models/world.go @@ -0,0 +1,10 @@ +package models + +type World struct { + ID int32 `gorm:"primaryKey" json:"id"` + RandomNumber int32 `gorm:"column:randomnumber" json:"randomNumber"` +} + +func (r *World) TableName() string { + return "World" +} diff --git a/frameworks/Go/goravel/src/gin/app/providers/route_service_provider.go b/frameworks/Go/goravel/src/gin/app/providers/route_service_provider.go new file mode 100644 index 00000000000..2e96015a24f --- /dev/null +++ b/frameworks/Go/goravel/src/gin/app/providers/route_service_provider.go @@ -0,0 +1,16 @@ +package providers + +import ( + "github.com/goravel/framework/contracts/foundation" + + "goravel/routes" +) + +type RouteServiceProvider struct{} + +func (receiver *RouteServiceProvider) Register(app foundation.Application) { +} + +func (receiver *RouteServiceProvider) Boot(app foundation.Application) { + routes.Web() +} diff --git a/frameworks/Go/goravel/src/gin/config/app.go b/frameworks/Go/goravel/src/gin/config/app.go new file mode 100644 index 00000000000..f6f898c90fd --- /dev/null +++ b/frameworks/Go/goravel/src/gin/config/app.go @@ -0,0 +1,40 @@ +package config + +import ( + "github.com/goravel/framework/cache" + "github.com/goravel/framework/console" + "github.com/goravel/framework/contracts/foundation" + "github.com/goravel/framework/database" + "github.com/goravel/framework/facades" + "github.com/goravel/framework/http" + "github.com/goravel/framework/log" + "github.com/goravel/framework/route" + "github.com/goravel/framework/validation" + "github.com/goravel/gin" + + "goravel/app/providers" +) + +// Boot Start all init methods of the current folder to bootstrap all config. +func Boot() {} + +func init() { + config := facades.Config() + config.Add("app", map[string]any{ + "name": "Goravel", + "env": "production", + "debug": false, + "key": config.Env("APP_KEY", ""), + "providers": []foundation.ServiceProvider{ + &log.ServiceProvider{}, + &console.ServiceProvider{}, + &database.ServiceProvider{}, + &cache.ServiceProvider{}, + &http.ServiceProvider{}, + &route.ServiceProvider{}, + &validation.ServiceProvider{}, + &providers.RouteServiceProvider{}, + &gin.ServiceProvider{}, + }, + }) +} diff --git a/frameworks/Go/goravel/src/gin/config/cache.go b/frameworks/Go/goravel/src/gin/config/cache.go new file mode 100644 index 00000000000..3c638243c2c --- /dev/null +++ b/frameworks/Go/goravel/src/gin/config/cache.go @@ -0,0 +1,18 @@ +package config + +import ( + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("cache", map[string]any{ + "default": "memory", + "stores": map[string]any{ + "memory": map[string]any{ + "driver": "memory", + }, + }, + "prefix": "goravel_cache", + }) +} diff --git a/frameworks/Go/goravel/src/gin/config/database.go b/frameworks/Go/goravel/src/gin/config/database.go new file mode 100644 index 00000000000..e1b1eb3272a --- /dev/null +++ b/frameworks/Go/goravel/src/gin/config/database.go @@ -0,0 +1,32 @@ +package config + +import ( + "github.com/goravel/framework/facades" +) + +func init() { + config := facades.Config() + config.Add("database", map[string]any{ + "default": "postgresql", + "connections": map[string]any{ + "postgresql": map[string]any{ + "driver": "postgresql", + "host": config.Env("DB_HOST", "tfb-database"), + "port": config.Env("DB_PORT", 5432), + "database": config.Env("DB_DATABASE", "hello_world"), + "username": config.Env("DB_USERNAME", "benchmarkdbuser"), + "password": config.Env("DB_PASSWORD", "benchmarkdbpass"), + "sslmode": "disable", + "timezone": "UTC", + "prefix": "", + "singular": true, + }, + }, + "pool": map[string]any{ + "max_idle_conns": 100, + "max_open_conns": 2000, + "conn_max_idletime": 3600, + "conn_max_lifetime": 3600, + }, + }) +} diff --git a/frameworks/Go/goravel/src/gin/config/http.go b/frameworks/Go/goravel/src/gin/config/http.go new file mode 100644 index 00000000000..9d8846ee610 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/config/http.go @@ -0,0 +1,30 @@ +package config + +import ( + "github.com/gin-gonic/gin/render" + "github.com/goravel/framework/contracts/route" + "github.com/goravel/framework/facades" + "github.com/goravel/gin" + ginfacades "github.com/goravel/gin/facades" +) + +func init() { + config := facades.Config() + config.Add("http", map[string]any{ + "default": "gin", + "drivers": map[string]any{ + "gin": map[string]any{ + "body_limit": 4096, + "header_limit": 4096, + "route": func() (route.Route, error) { + return ginfacades.Route("gin"), nil + }, + "template": func() (render.HTMLRender, error) { + return gin.DefaultTemplate() + }, + }, + }, + "host": "", + "port": "8080", + }) +} diff --git a/frameworks/Go/goravel/src/gin/config/json.go b/frameworks/Go/goravel/src/gin/config/json.go new file mode 100644 index 00000000000..2b2e1af3f80 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/config/json.go @@ -0,0 +1,31 @@ +package config + +import ( + "github.com/bytedance/sonic" + "github.com/goravel/framework/contracts/foundation" + "github.com/goravel/framework/facades" +) + +func init() { + facades.App().SetJson(NewJson()) +} + +type Json struct { + marshal func(any) ([]byte, error) + unmarshal func([]byte, any) error +} + +func NewJson() foundation.Json { + return &Json{ + marshal: sonic.Marshal, + unmarshal: sonic.Unmarshal, + } +} + +func (j *Json) Marshal(v any) ([]byte, error) { + return j.marshal(v) +} + +func (j *Json) Unmarshal(data []byte, v any) error { + return j.unmarshal(data, v) +} diff --git a/frameworks/Go/goravel/src/gin/go.mod b/frameworks/Go/goravel/src/gin/go.mod new file mode 100644 index 00000000000..93ac7f3ec4e --- /dev/null +++ b/frameworks/Go/goravel/src/gin/go.mod @@ -0,0 +1,194 @@ +module goravel + +go 1.22 + +require ( + github.com/bytedance/sonic v1.11.9 + github.com/gin-gonic/gin v1.10.0 + github.com/goravel/framework v1.14.1 + github.com/goravel/gin v1.2.1 +) + +require ( + atomicgo.dev/cursor v0.2.0 // indirect + atomicgo.dev/keyboard v0.2.9 // indirect + atomicgo.dev/schedule v0.1.0 // indirect + cloud.google.com/go v0.112.1 // indirect + cloud.google.com/go/compute v1.25.1 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/pubsub v1.36.1 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.16 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae // indirect + github.com/RichardKnop/machinery/v2 v2.0.13 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aws/aws-sdk-go v1.49.6 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/catppuccin/go v0.2.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/charmbracelet/bubbles v0.18.0 // indirect + github.com/charmbracelet/bubbletea v0.26.3 // indirect + github.com/charmbracelet/huh v0.4.2 // indirect + github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0 // indirect + github.com/charmbracelet/lipgloss v0.11.0 // indirect + github.com/charmbracelet/x/ansi v0.1.1 // indirect + github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a // indirect + github.com/charmbracelet/x/input v0.1.1 // indirect + github.com/charmbracelet/x/term v0.1.1 // indirect + github.com/charmbracelet/x/windows v0.1.2 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.4 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.22.0 // indirect + github.com/glebarez/sqlite v1.11.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/go-redsync/redsync/v4 v4.8.1 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/go-stack/stack v1.8.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang-migrate/migrate/v4 v4.17.1 // indirect + github.com/golang-module/carbon/v2 v2.3.12 // indirect + github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect + github.com/golang-sql/sqlexp v0.1.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/gomodule/redigo v2.0.0+incompatible // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/google/wire v0.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.3 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/gookit/filter v1.2.1 // indirect + github.com/gookit/goutil v0.6.15 // indirect + github.com/gookit/validate v1.5.2 // indirect + github.com/goravel/file-rotatelogs/v2 v2.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgx/v5 v5.5.4 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/kelseyhightower/envconfig v1.4.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/lithammer/fuzzysearch v1.1.8 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect + github.com/microsoft/go-mssqldb v1.6.0 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.15.2 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/pterm/pterm v0.12.79 // indirect + github.com/rabbitmq/amqp091-go v1.9.0 // indirect + github.com/redis/go-redis/v9 v9.5.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/robfig/cron/v3 v3.0.1 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/rotisserie/eris v0.5.4 // indirect + github.com/rs/cors v1.11.0 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/savioxavier/termlink v1.3.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.19.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + github.com/unrolled/secure v1.14.0 // indirect + github.com/urfave/cli/v2 v2.27.2 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.1 // indirect + github.com/xdg-go/stringprep v1.0.3 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + go.mongodb.org/mongo-driver v1.7.5 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.171.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect + google.golang.org/grpc v1.64.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.6 // indirect + gorm.io/driver/postgres v1.5.7 // indirect + gorm.io/driver/sqlserver v1.5.3 // indirect + gorm.io/gorm v1.25.10 // indirect + gorm.io/plugin/dbresolver v1.5.1 // indirect + modernc.org/libc v1.37.6 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.7.2 // indirect + modernc.org/sqlite v1.28.0 // indirect +) diff --git a/frameworks/Go/goravel/src/gin/go.sum b/frameworks/Go/goravel/src/gin/go.sum new file mode 100644 index 00000000000..92b222fbcbb --- /dev/null +++ b/frameworks/Go/goravel/src/gin/go.sum @@ -0,0 +1,1170 @@ +atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= +atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= +atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= +atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= +atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= +atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= +atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= +atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM= +cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/pubsub v1.10.0/go.mod h1:eNpTrkOy7dCpkNyaSNetMa6udbgecJMd0ZsTJS/cuNo= +cloud.google.com/go/pubsub v1.36.1 h1:dfEPuGCHGbWUhaMCTHUFjfroILEkx55iUmKBZTP5f+Y= +cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.4.0/go.mod h1:ON4tFdPTwRcgWEaVDrN3584Ef+b7GgSJaXxe5fW9t4M= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1 h1:/iHxaJhsFr0+xVFfbMr5vxz848jyiWuIEDhYq3y5odY= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.1.2/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.2.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0 h1:yfJe15aSwEQ6Oo6J+gdfdulPNoZ3TEhmbhLIoxZcA+U= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.0/go.mod h1:Q28U+75mpCaSCDowNEmhIo/rmgdkqmkmzI7N6TGR4UY= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0 h1:T028gtTPiYt/RMUfs8nVsAL7FDQrfLlrm/NnRG/zcC4= +github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v0.8.0/go.mod h1:cw4zVQgBby0Z5f2v0itn6se2dDP17nTjbZFXW5uPyHA= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest/adal v0.9.16 h1:P8An8Z9rH1ldbOLdFpxYorgOt2sywL9V24dAwWHPuGc= +github.com/Azure/go-autorest/autorest/adal v0.9.16/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0 h1:HCc0+LpPfpCKs6LGGLAhwBARt9632unrVcI6i8s/8os= +github.com/AzureAD/microsoft-authentication-library-for-go v1.1.0/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= +github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= +github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= +github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= +github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= +github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= +github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= +github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= +github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae h1:DcFpTQBYQ9Ct2d6sC7ol0/ynxc2pO1cpGUM+f4t5adg= +github.com/RichardKnop/logging v0.0.0-20190827224416-1a693bdd4fae/go.mod h1:rJJ84PyA/Wlmw1hO+xTzV2wsSUon6J5ktg0g8BF2PuU= +github.com/RichardKnop/machinery/v2 v2.0.13 h1:uo9htg+qNBi7UeUK3jcTBl3vTO/vvLKGaOdCOKePl50= +github.com/RichardKnop/machinery/v2 v2.0.13/go.mod h1:Yc2X/QRm9rRfAjB+93NGR+kSUqtnqqs8kME4L+TKKiw= +github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/aws/aws-sdk-go v1.37.16/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.49.6 h1:yNldzF5kzLBRvKlKz1S0bkvc2+04R1kt13KfBWQBfFA= +github.com/aws/aws-sdk-go v1.49.6/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/brianvoe/gofakeit/v6 v6.28.0 h1:Xib46XXuQfmlLS2EXRuJpqcw8St6qSZz75OUo0tgAW4= +github.com/brianvoe/gofakeit/v6 v6.28.0/go.mod h1:Xj58BMSnFqcn/fAQeSK+/PLtC5kSb7FJIq4JyGa8vEs= +github.com/bsm/ginkgo/v2 v2.5.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.20.0/go.mod h1:JifAceMQ4crZIWYUKrlGcmbN3bqHogVTADMD2ATsbwk= +github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5zg= +github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA= +github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbles v0.18.0 h1:PYv1A036luoBGroX6VWjQIE9Syf2Wby2oOl/39KLfy0= +github.com/charmbracelet/bubbles v0.18.0/go.mod h1:08qhZhtIwzgrtBjAcJnij1t1H0ZRjwHyGsy6AL11PSw= +github.com/charmbracelet/bubbletea v0.26.3 h1:iXyGvI+FfOWqkB2V07m1DF3xxQijxjY2j8PqiXYqasg= +github.com/charmbracelet/bubbletea v0.26.3/go.mod h1:bpZHfDHTYJC5g+FBK+ptJRCQotRC+Dhh3AoMxa/2+3Q= +github.com/charmbracelet/huh v0.4.2 h1:5wLkwrA58XDAfEZsJzNQlfJ+K8N9+wYwvR5FOM7jXFM= +github.com/charmbracelet/huh v0.4.2/go.mod h1:g9OXBgtY3zRV4ahnVih9bZE+1yGYN+y2C9Q6L2P+WM0= +github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0 h1:79JTuYRirtyCn9ac6rzPt5AQKtBDFc1gKxpw0wBrI+Y= +github.com/charmbracelet/huh/spinner v0.0.0-20240508140610-13957916abf0/go.mod h1:Zxt9FH6togK9kY71pRJGtmyNkJ1eIWdK1gRaXrS/FKA= +github.com/charmbracelet/lipgloss v0.11.0 h1:UoAcbQ6Qml8hDwSWs0Y1cB5TEQuZkDPH/ZqwWWYTG4g= +github.com/charmbracelet/lipgloss v0.11.0/go.mod h1:1UdRTH9gYgpcdNN5oBtjbu/IzNKtzVtb7sqN1t9LNn8= +github.com/charmbracelet/x/ansi v0.1.1 h1:CGAduulr6egay/YVbGc8Hsu8deMg1xZ/bkaXTPi1JDk= +github.com/charmbracelet/x/ansi v0.1.1/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a h1:lOpqe2UvPmlln41DGoii7wlSZ/q8qGIon5JJ8Biu46I= +github.com/charmbracelet/x/exp/strings v0.0.0-20240524151031-ff83003bf67a/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ= +github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a h1:k/s6UoOSVynWiw7PlclyGO2VdVs5ZLbMIHiGp4shFZE= +github.com/charmbracelet/x/exp/term v0.0.0-20240524151031-ff83003bf67a/go.mod h1:YBotIGhfoWhHDlnUpJMkjebGV2pdGRCn1Y4/Nk/vVcU= +github.com/charmbracelet/x/input v0.1.1 h1:YDOJaTUKCqtGnq9PHzx3pkkl4pXDOANUHmhH3DqMtM4= +github.com/charmbracelet/x/input v0.1.1/go.mod h1:jvdTVUnNWj/RD6hjC4FsoB0SeZCJ2ZBkiuFP9zXvZI0= +github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= +github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= +github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelhxojXlRWg= +github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg= +github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA= +github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= +github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= +github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= +github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= +github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-redsync/redsync/v4 v4.8.1 h1:rq2RvdTI0obznMdxKUWGdmmulo7lS9yCzb8fgDKOlbM= +github.com/go-redsync/redsync/v4 v4.8.1/go.mod h1:LmUAsQuQxhzZAoGY7JS6+dNhNmZyonMZiiEDY9plotM= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= +github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= +github.com/golang-module/carbon/v2 v2.3.12 h1:VC1DwN1kBwJkh5MjXmTFryjs5g4CWyoM8HAHffZPX/k= +github.com/golang-module/carbon/v2 v2.3.12/go.mod h1:HNsedGzXGuNciZImYP2OMnpiwq/vhIstR/vn45ib5cI= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI= +github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= +github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gookit/filter v1.2.1 h1:37XivkBm2E5qe1KaGdJ5ZfF5l9NYdGWfLEeQadJD8O4= +github.com/gookit/filter v1.2.1/go.mod h1:rxynQFr793x+XDwnRmJFEb53zDw0Zqx3OD7TXWoR9mQ= +github.com/gookit/goutil v0.6.15 h1:mMQ0ElojNZoyPD0eVROk5QXJPh2uKR4g06slgPDF5Jo= +github.com/gookit/goutil v0.6.15/go.mod h1:qdKdYEHQdEtyH+4fNdQNZfJHhI0jUZzHxQVAV3DaMDY= +github.com/gookit/validate v1.5.2 h1:i5I2OQ7WYHFRPRATGu9QarR9snnNHydvwSuHXaRWAV0= +github.com/gookit/validate v1.5.2/go.mod h1:yuPy2WwDlwGRa06fFJ5XIO8QEwhRnTC2LmxmBa5SE14= +github.com/goravel/file-rotatelogs/v2 v2.4.2 h1:g68AzbePXcm0V2CpUMc9j4qVzcDn7+7aoWSjZ51C0m4= +github.com/goravel/file-rotatelogs/v2 v2.4.2/go.mod h1:23VuSW8cBS4ax5cmbV+5AaiLpq25b8UJ96IhbAkdo8I= +github.com/goravel/framework v1.14.1 h1:VcJvzn1ItFQh/rQZO1EMkxKmzDrww1S+OGz4hjZi3UY= +github.com/goravel/framework v1.14.1/go.mod h1:rScDXGQZdoVfyxemNPmijlz/2a+lWNOa4jTuak5GGVg= +github.com/goravel/gin v1.2.1 h1:lnQX3NKUEaSx8x7AAJpoeVkXgi+MVQ9FXy4QywHQElo= +github.com/goravel/gin v1.2.1/go.mod h1:Qt3NJysg/eoxXL4y/swwFUcfcIT7XG+xb0rWChweZfY= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8= +github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= +github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= +github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo= +github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg= +github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= +github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= +github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= +github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= +github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= +github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= +github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= +github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= +github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= +github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= +github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= +github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4= +github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo= +github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc3Aoo= +github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc= +github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps= +github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU= +github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo= +github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk= +github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s= +github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po= +github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/savioxavier/termlink v1.3.0 h1:3Gl4FzQjUyiHzmoEDfmWEhgIwDiJY4poOQHP+k8ReA4= +github.com/savioxavier/termlink v1.3.0/go.mod h1:5T5ePUlWbxCHIwyF8/Ez1qufOoGM89RCg9NvG+3G3gc= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= +github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/unrolled/secure v1.14.0 h1:u9vJTU/pR4Bny0ntLUMxdfLtmIRGvQf2sEFuA0TG9AE= +github.com/unrolled/secure v1.14.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= +github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/scram v1.1.1 h1:VOMT+81stJgXW3CpHyqHN3AXDYIMsx56mEFrB37Mb/E= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg-go/stringprep v1.0.3 h1:kdwGpVNwPFtjs98xCGkHjQtGKh86rDcRZN17QEMCOIs= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= +github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= +github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.einride.tech/aip v0.66.0 h1:XfV+NQX6L7EOYK11yoHHFtndeaWh3KbD9/cN/6iWEt8= +go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M= +go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.mongodb.org/mongo-driver v1.7.5 h1:ny3p0reEpgsR2cfA5cjgwFZg3Cv/ofFh/8jbhGtz9VI= +go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.39.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.171.0 h1:w174hnBPqut76FzW5Qaupt7zY8Kql6fiVjgys4f58sU= +google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY= +google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 h1:RFiFrvy37/mpSpdySBDrUdipW/dHwsRwh3J3+A9VgT4= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/mysql v1.5.6 h1:Ld4mkIickM+EliaQZQx3uOJDJHtrd70MxAUqWqlx3Y8= +gorm.io/driver/mysql v1.5.6/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM= +gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA= +gorm.io/driver/sqlserver v1.5.3 h1:rjupPS4PVw+rjJkfvr8jn2lJ8BMhT4UW5FwuJY0P3Z0= +gorm.io/driver/sqlserver v1.5.3/go.mod h1:B+CZ0/7oFJ6tAlefsKoyxdgDCXJKSgwS2bMOQZT0I00= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s= +gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/plugin/dbresolver v1.5.1 h1:s9Dj9f7r+1rE3nx/Ywzc85nXptUEaeOO0pt27xdopM8= +gorm.io/plugin/dbresolver v1.5.1/go.mod h1:l4Cn87EHLEYuqUncpEeTC2tTJQkjngPSD+lo8hIvcT0= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw= +modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/frameworks/Go/goravel/src/gin/main.go b/frameworks/Go/goravel/src/gin/main.go new file mode 100644 index 00000000000..ddd89a4e1a1 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "github.com/goravel/framework/facades" + "github.com/goravel/framework/foundation" + + "goravel/config" +) + +func main() { + app := foundation.NewApplication() + + // Bootstrap the application + app.Boot() + + // Bootstrap the config. + config.Boot() + + // Start HTTP server by facades.Route(). + go func() { + if err := facades.Route().Run(); err != nil { + facades.Log().Errorf("Route run error: %v", err) + } + }() + + select {} +} diff --git a/frameworks/Go/goravel/src/gin/resources/views/fortunes.tmpl b/frameworks/Go/goravel/src/gin/resources/views/fortunes.tmpl new file mode 100644 index 00000000000..4c58fa53da0 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/resources/views/fortunes.tmpl @@ -0,0 +1,22 @@ +{{define "fortunes.tmpl"}} + + + + Fortunes + + + + + + + + {{range .fortunes}} + + + + + {{end}} +
idmessage
{{.ID}}{{.Message}}
+ + +{{end}} diff --git a/frameworks/Go/goravel/src/gin/routes/web.go b/frameworks/Go/goravel/src/gin/routes/web.go new file mode 100644 index 00000000000..86bfbccc2d4 --- /dev/null +++ b/frameworks/Go/goravel/src/gin/routes/web.go @@ -0,0 +1,19 @@ +package routes + +import ( + "github.com/goravel/framework/facades" + + "goravel/app/http/controllers" +) + +func Web() { + testController := controllers.NewTestController() + facades.Route().Get("/plaintext", testController.Plaintext) + facades.Route().Get("/json", testController.JSON) + facades.Route().Get("/db", testController.DB) + facades.Route().Get("/queries", testController.Queries) + facades.Route().Get("/update", testController.Update) + facades.Route().Get("/fortunes", testController.Fortunes) + facades.Route().Get("/cached-worlds", testController.CacheQueries) + +} From c225d2aac662fc647e7a2b85c59c44b0ce52aff5 Mon Sep 17 00:00:00 2001 From: pavelmash <7467039+pavelmash@users.noreply.github.com> Date: Mon, 1 Jul 2024 20:50:03 +0300 Subject: [PATCH 09/62] [mORMot] fixed GPF on plaintext endpoint 2.2.7693 (#9121) Co-authored-by: pavel.mash --- frameworks/Pascal/mormot/setup_and_build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Pascal/mormot/setup_and_build.sh b/frameworks/Pascal/mormot/setup_and_build.sh index 85863798754..ed0c26034e8 100755 --- a/frameworks/Pascal/mormot/setup_and_build.sh +++ b/frameworks/Pascal/mormot/setup_and_build.sh @@ -35,7 +35,7 @@ echo "Download statics from $URL ..." wget -qO- "$URL" | tar -xz -C ./libs/mORMot/static # uncomment for fixed commit URL -URL=https://github.com/synopse/mORMot2/tarball/f0fc66c954cd45f5c581e52c21170923805a683b +URL=https://github.com/synopse/mORMot2/tarball/a0dda41833c3d32531080d1eeb5a1627540d62e9 #URL="https://api.github.com/repos/synopse/mORMot2/tarball/$USED_TAG" echo "Download and unpacking mORMot sources from $URL ..." wget -qO- "$URL" | tar -xz -C ./libs/mORMot --strip-components=1 From 3c91fd5b639be1383bdeef90ed69005a72b87d2a Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 2 Jul 2024 01:50:14 +0800 Subject: [PATCH 10/62] beetlex update RawDb (#9117) * update beetleX to BeetleX.Light * update beetlex to beetlex.light * fix fortunes error * fix error * remove beetlex-core-updb * update * update benchmark_config * update * update * update * update RawDb * update * update * update * update * update dbraw --- .../beetlex/PlatformBenchmarks/DBRaw.cs | 425 ++++++++---------- .../beetlex/PlatformBenchmarks/GMTDate.cs | 14 +- .../PlatformBenchmarks/HttpHandler.Caching.cs | 2 +- .../beetlex/PlatformBenchmarks/HttpHandler.cs | 22 +- .../PlatformBenchmarks/HttpHandler.db.cs | 4 +- .../HttpHandler.fortunes.cs | 24 +- .../PlatformBenchmarks/HttpHandler.json.cs | 10 +- .../HttpHandler.plaintext.cs | 23 +- .../PlatformBenchmarks/HttpHandler.queries.cs | 2 +- .../PlatformBenchmarks/HttpHandler.updates.cs | 2 +- .../beetlex/PlatformBenchmarks/HttpServer.cs | 28 +- .../PlatformBenchmarks.csproj | 2 +- .../beetlex/PlatformBenchmarks/Program.cs | 1 - 13 files changed, 243 insertions(+), 316 deletions(-) diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs index ca668243fe7..6aae831fcbb 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/DBRaw.cs @@ -10,110 +10,44 @@ using Microsoft.Extensions.Caching.Memory; using Npgsql; +using System.Runtime.CompilerServices; namespace PlatformBenchmarks { - public class RawDb + public sealed class RawDb { - private readonly ConcurrentRandom _random; + private readonly MemoryCache _cache + = new(new MemoryCacheOptions { ExpirationScanFrequency = TimeSpan.FromMinutes(60) }); - private readonly DbProviderFactory _dbProviderFactory; - - private readonly static MemoryCache _cache = new MemoryCache( - new MemoryCacheOptions() - { - ExpirationScanFrequency = TimeSpan.FromMinutes(60) - }); - - private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray(); + private static DbProviderFactory _dbProviderFactory => Npgsql.NpgsqlFactory.Instance; + private readonly string _connectionString; - public static string _connectionString = null; - - public RawDb(ConcurrentRandom random, DbProviderFactory dbProviderFactory) + public RawDb(ConcurrentRandom random, string connectionString) { _random = random; - _dbProviderFactory = dbProviderFactory; - OnCreateCommand(); - } - private void OnCreateCommand() - { - SingleCommand = new Npgsql.NpgsqlCommand(); - SingleCommand.CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id"; - mID = new Npgsql.NpgsqlParameter("@Id", _random.Next(1, 10001)); - SingleCommand.Parameters.Add(mID); - FortuneCommand = new Npgsql.NpgsqlCommand(); - FortuneCommand.CommandText = "SELECT id, message FROM fortune"; - } - - private DbCommand SingleCommand; - - private DbCommand FortuneCommand; - - private Npgsql.NpgsqlParameter mID; - - private static int ListDefaultSize = 8; - - private World[] mWorldBuffer = null; - - private World[] GetWorldBuffer() - { - if (mWorldBuffer == null) - mWorldBuffer = new World[512]; - return mWorldBuffer; - } - - private Fortune[] mFortunesBuffer = null; - - private Fortune[] GetFortuneBuffer() - { - if (mFortunesBuffer == null) - mFortunesBuffer = new Fortune[512]; - return mFortunesBuffer; + _connectionString = connectionString; } public async Task LoadSingleQueryRow() { - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - await db.OpenAsync(); - SingleCommand.Connection = db; - mID.TypedValue = _random.Next(1, 10001); - return await ReadSingleRow(db, SingleCommand); - - } - } - - async Task ReadSingleRow(DbConnection connection, DbCommand cmd) - { - using (var rdr = await cmd.ExecuteReaderAsync(CommandBehavior.SingleRow)) - + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) { - await rdr.ReadAsync(); - return new World + connection.ConnectionString = _connectionString; + await connection.OpenAsync(); + var (cmd, _) = CreateReadCommand(connection); + using (var command = cmd) { - Id = rdr.GetInt32(0), - RandomNumber = rdr.GetInt32(1) - }; - } - } - public async Task> LoadMultipleQueriesRows(int count) - { - using (var db = _dbProviderFactory.CreateConnection()) - { - db.ConnectionString = _connectionString; - await db.OpenAsync(); - return await LoadMultipleRows(count, db); + return await ReadSingleRow(cmd); + } } } - - public Task LoadCachedQueries(int count) + public Task LoadCachedQueries(int count) { - var result = new World[count]; + var result = new CachedWorld[count]; var cacheKeys = _cacheKeys; var cache = _cache; var random = _random; @@ -121,42 +55,40 @@ public Task LoadCachedQueries(int count) { var id = random.Next(1, 10001); var key = cacheKeys[id]; - var data = cache.Get(key); - - if (data != null) + if (cache.TryGetValue(key, out var cached)) { - result[i] = data; + result[i] = (CachedWorld)cached; } else { - return LoadUncachedQueries(id, i, count, this, result); + return LoadUncachedQueries(_connectionString, id, i, count, this, result); } } return Task.FromResult(result); - static async Task LoadUncachedQueries(int id, int i, int count, RawDb rawdb, World[] result) + static async Task LoadUncachedQueries(string conn, int id, int i, int count, RawDb rawdb, CachedWorld[] result) { - using (var db = new NpgsqlConnection(_connectionString)) + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) { - await db.OpenAsync(); - Func> create = async (entry) => - { - return await rawdb.ReadSingleRow(db, rawdb.SingleCommand); - }; + connection.ConnectionString = conn; + await connection.OpenAsync(); + var (cmd, idParameter) = rawdb.CreateReadCommand(connection); + using var command = cmd; + async Task create(ICacheEntry _) => await ReadSingleRow(cmd); + var cacheKeys = _cacheKeys; var key = cacheKeys[id]; - rawdb.SingleCommand.Connection = db; - rawdb.mID.TypedValue = id; + idParameter.TypedValue = id; + for (; i < result.Length; i++) { - var data = await _cache.GetOrCreateAsync(key, create); - result[i] = data; + result[i] = await rawdb._cache.GetOrCreateAsync(key, create); + id = rawdb._random.Next(1, 10001); - rawdb.SingleCommand.Connection = db; - rawdb.mID.TypedValue = id; + idParameter.TypedValue = id; key = cacheKeys[id]; } } @@ -164,215 +96,212 @@ static async Task LoadUncachedQueries(int id, int i, int count, RawDb r } } - - private async Task> LoadMultipleRows(int count, DbConnection db) + public async Task PopulateCache() { - SingleCommand.Connection = db; - SingleCommand.Parameters[0].Value = _random.Next(1, 10001); - var result = GetWorldBuffer(); - for (int i = 0; i < count; i++) + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) { - result[i] = await ReadSingleRow(db, SingleCommand); - SingleCommand.Parameters[0].Value = _random.Next(1, 10001); + connection.ConnectionString = _connectionString; + await connection.OpenAsync(); + var (cmd, idParameter) = CreateReadCommand(connection); + using var command = cmd; + + var cacheKeys = _cacheKeys; + var cache = _cache; + for (var i = 1; i < 10001; i++) + { + idParameter.TypedValue = i; + cache.Set(cacheKeys[i], await ReadSingleRow(cmd)); + } } - return new ArraySegment(result, 0, count); + Console.WriteLine("Caching Populated"); } - public async Task> LoadFortunesRows() + public async Task LoadMultipleQueriesRows(int count) { - int count = 0; - var result = GetFortuneBuffer(); - using (var db = new NpgsqlConnection(_connectionString)) + var results = new World[count]; + + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) { - await db.OpenAsync(); - FortuneCommand.Connection = db; - using (var rdr = await FortuneCommand.ExecuteReaderAsync()) + connection.ConnectionString = _connectionString; + await connection.OpenAsync(); + + using var batch = new NpgsqlBatch(connection) + { + // Inserts a PG Sync message between each statement in the batch, required for compliance with + // TechEmpower general test requirement 7 + // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview + EnableErrorBarriers = true + }; + + for (var i = 0; i < count; i++) { - while (await rdr.ReadAsync()) + batch.BatchCommands.Add(new() { - result[count] = (new Fortune - { - Id = rdr.GetInt32(0), - Message = rdr.GetString(1) - }); - count++; - } + CommandText = "SELECT id, randomnumber FROM world WHERE id = $1", + Parameters = { new NpgsqlParameter { TypedValue = _random.Next(1, 10001) } } + }); + } + + using var reader = await batch.ExecuteReaderAsync(); + + for (var i = 0; i < count; i++) + { + await reader.ReadAsync(); + results[i] = new World { Id = reader.GetInt32(0), RandomNumber = reader.GetInt32(1) }; + await reader.NextResultAsync(); } } - result[count] = (new Fortune { Message = "Additional fortune added at request time." }); - count++; - Array.Sort(result, 0, count); - return new ArraySegment(result, 0, count); + return results; } + public async Task LoadMultipleUpdatesRows(int count) { - using (var db = new NpgsqlConnection(_connectionString)) + var results = new World[count]; + + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) { - await db.OpenAsync(); - var updateCmd = UpdateCommandsCached.PopCommand(count); - try + connection.ConnectionString = _connectionString; + await connection.OpenAsync(); + var (queryCmd, queryParameter) = CreateReadCommand(connection); + using (queryCmd) { - var command = updateCmd.Command; - command.Connection = db; - SingleCommand.Connection = db; - mID.TypedValue = _random.Next(1, int.MaxValue) % 10000 + 1; - var results = new World[count]; - for (int i = 0; i < count; i++) + for (var i = 0; i < results.Length; i++) { - results[i] = await ReadSingleRow(db, SingleCommand); - mID.TypedValue = _random.Next(1, int.MaxValue) % 10000 + 1; + results[i] = await ReadSingleRow(queryCmd); + queryParameter.TypedValue = _random.Next(1, 10001); } + } - for (int i = 0; i < count; i++) + using (var updateCmd = new NpgsqlCommand(BatchUpdateString.Query(count), connection)) + { + for (var i = 0; i < results.Length; i++) { - var randomNumber = _random.Next(1, int.MaxValue) % 10000 + 1; - updateCmd.Parameters[i * 2].TypedValue = results[i].Id; - updateCmd.Parameters[i * 2 + 1].TypedValue = randomNumber; - //updateCmd.Parameters[i * 2].Value = results[i].Id; - //updateCmd.Parameters[i * 2 + 1].Value = randomNumber; + var randomNumber = _random.Next(1, 10001); + + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = results[i].Id }); + updateCmd.Parameters.Add(new NpgsqlParameter { TypedValue = randomNumber }); + results[i].RandomNumber = randomNumber; } - await command.ExecuteNonQueryAsync(); - return results; - } - catch (Exception e_) - { - throw e_; - } - finally - { - UpdateCommandsCached.PushCommand(count, updateCmd); + await updateCmd.ExecuteNonQueryAsync(); } } - } - } + return results; + } - public sealed class CacheKey : IEquatable - { - private readonly int _value; + public async Task> LoadFortunesRows() + { + // Benchmark requirements explicitly prohibit pre-initializing the list size + var result = new List(); - public CacheKey(int value) - => _value = value; + using (var connection = (NpgsqlConnection)_dbProviderFactory.CreateConnection()) + { + connection.ConnectionString = _connectionString; + await connection.OpenAsync(); - public bool Equals(CacheKey key) - => key._value == _value; + using (var cmd = new NpgsqlCommand("SELECT id, message FROM fortune", connection)) + { - public override bool Equals(object obj) - => ReferenceEquals(obj, this); + using (var rdr = await cmd.ExecuteReaderAsync()) + { - public override int GetHashCode() - => _value; + while (await rdr.ReadAsync()) + { + result.Add(new Fortune + { + Id = rdr.GetInt32(0), + Message = rdr.GetString(1) + }); + } + } + } + } + result.Add(new Fortune { Message = "Additional fortune added at request time." }); + result.Sort(); - public override string ToString() - => _value.ToString(); - } + return result; + } - internal class UpdateCommandsCached - { - private static System.Collections.Concurrent.ConcurrentStack[] mCacheTable - = new System.Collections.Concurrent.ConcurrentStack[1024]; - public static string[] IDParamereNames = new string[1024]; + private (NpgsqlCommand readCmd, NpgsqlParameter idParameter) CreateReadCommand(NpgsqlConnection connection) + { + var cmd = new NpgsqlCommand("SELECT id, randomnumber FROM world WHERE id = $1", connection); + var parameter = new NpgsqlParameter { TypedValue = _random.Next(1, 10001) }; - public static string[] RandomParamereNames = new string[1024]; + cmd.Parameters.Add(parameter); - static UpdateCommandsCached() - { - for (int i = 0; i < 1024; i++) - { - IDParamereNames[i] = $"@Id_{i}"; - RandomParamereNames[i] = $"@Random_{i}"; - mCacheTable[i] = new System.Collections.Concurrent.ConcurrentStack(); - } + return (cmd, parameter); } - private static CommandCacheItem CreatCommand(int count) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static async Task ReadSingleRow(NpgsqlCommand cmd) { - CommandCacheItem item = new CommandCacheItem(); - NpgsqlCommand cmd = new Npgsql.NpgsqlCommand(); - cmd.CommandText = BatchUpdateString.Query(count); - for (int i = 0; i < count; i++) - { - var id = new NpgsqlParameter(); - id.ParameterName = IDParamereNames[i]; - cmd.Parameters.Add(id); - item.Parameters.Add(id); - - var random = new NpgsqlParameter(); - random.ParameterName = RandomParamereNames[i]; - cmd.Parameters.Add(random); - item.Parameters.Add(random); - } - item.Command = cmd; - return item; + using var rdr = await cmd.ExecuteReaderAsync(System.Data.CommandBehavior.SingleRow); + await rdr.ReadAsync(); + return new World + { + Id = rdr.GetInt32(0), + RandomNumber = rdr.GetInt32(1) + }; } - public static void PushCommand(int count, CommandCacheItem cmd) - { - mCacheTable[count].Push(cmd); - } + private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray(); - public static CommandCacheItem PopCommand(int count) + public sealed class CacheKey : IEquatable { - if (mCacheTable[count].TryPop(out CommandCacheItem cmd)) - return cmd; - return CreatCommand(count); - } + private readonly int _value; - private static bool mInited = false; + public CacheKey(int value) + => _value = value; - public static void Init() - { - if (mInited) - return; - lock (typeof(UpdateCommandsCached)) - { - if (mInited) - return; - for (int i = 1; i <= 500; i++) - { - for (int k = 0; k < 10; k++) - { - var cmd = CreatCommand(i); - mCacheTable[i].Push(cmd); - } - } - mInited = true; - return; - } - } - } + public bool Equals(CacheKey key) + => key._value == _value; - class CommandCacheItem - { - public Npgsql.NpgsqlCommand Command { get; set; } + public override bool Equals(object obj) + => ReferenceEquals(obj, this); - public List> Parameters { get; private set; } = new List>(1024); + public override int GetHashCode() + => _value; + + public override string ToString() + => _value.ToString(); + } } - internal class BatchUpdateString + internal sealed class BatchUpdateString { private const int MaxBatch = 500; + internal static readonly string[] ParamNames = Enumerable.Range(0, MaxBatch * 2).Select(i => $"@p{i}").ToArray(); + private static string[] _queries = new string[MaxBatch + 1]; public static string Query(int batchSize) + => _queries[batchSize] is null + ? CreateBatch(batchSize) + : _queries[batchSize]; + + private static string CreateBatch(int batchSize) { - if (_queries[batchSize] != null) + var sb = StringBuilderCache.Acquire(); + + + sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES "); + var c = 1; + for (var i = 0; i < batchSize; i++) { - return _queries[batchSize]; + if (i > 0) + sb.Append(", "); + sb.Append($"(${c++}, ${c++})"); } + sb.Append(" ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id"); + - var lastIndex = batchSize - 1; - var sb = StringBuilderCache.Acquire(); - sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES "); - Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@Id_{i}, @Random_{i}), ")); - sb.Append($"(@Id_{lastIndex}, @Random_{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id"); return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb); } } diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs index 76e15ce9f7f..bfd6b79223a 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/GMTDate.cs @@ -49,7 +49,7 @@ public static GMTDate Default } } - public ArraySegment DATE + public Memory DATE { get; set; @@ -95,18 +95,20 @@ private void Init() }, null, 1000, 1000); } - private ArraySegment GetData() + private Memory GetData() { return GetData(DateTime.Now); } + + public void Write(IStreamWriter stream) { - var data = DATE; - stream.Write(data.Array, 0, data.Count); + + stream.Write(DATE.Span); } - private ArraySegment GetData(DateTime date) + private Memory GetData(DateTime date) { date = date.ToUniversalTime(); int offset13 = 0; @@ -190,7 +192,7 @@ private ArraySegment GetData(DateTime date) buffer[offset13] = _n; offset13++; - return new ArraySegment(GTM_BUFFER, 0, offset13); + return new Memory(GTM_BUFFER, 0, offset13); } } diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs index 2b2264ea60a..2794fcbdd82 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.Caching.cs @@ -33,7 +33,7 @@ public async Task caching(string queryString, IStreamWriter stream) ContentLengthMemory content = new ContentLengthMemory(); try { - var data = await _db.LoadCachedQueries(count); + var data = await DB.LoadCachedQueries(count); stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length); content.Data = GetContentLengthMemory(stream); GMTDate.Default.Write(stream); diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs index e623afdd72b..117d19fee9a 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.cs @@ -47,7 +47,6 @@ public partial class HttpHandler : SesionBase private static readonly AsciiString _path_Fortunes = "/fortunes"; - private static readonly AsciiString _result_plaintext = "Hello, World!"; private static readonly AsciiString _cached_worlds = "/cached-worlds"; @@ -55,19 +54,6 @@ public partial class HttpHandler : SesionBase - private readonly static AsciiString _jsonPreamble = - _httpsuccess - + _headerContentTypeJson - + _headerServer - + _headerContentLength + _jsonPayloadSize.ToString() + _line; - - private readonly static AsciiString _plaintextPreamble = - _httpsuccess - + _headerContentTypeText - + _headerServer - + _headerContentLength + _result_plaintext.Length.ToString() + _line; - - private readonly static AsciiString _jsonResultPreamble = _httpsuccess + _headerContentTypeJson @@ -122,14 +108,14 @@ public HttpHandler() private Queue _Requests = new Queue(); - private RawDb _db; + public static RawDb DB; private RequestData _ReadRequest = null; public override void Connected(NetContext context) { base.Connected(context); this.Context = context; - _db = new RawDb(new ConcurrentRandom(), Npgsql.NpgsqlFactory.Instance); ; + } private int AnalysisUrl(ReadOnlySpan url) @@ -255,11 +241,11 @@ private void AnalysisAction(ReadOnlySequence line, out ActionType type, ou Span baseUrl = stackalloc byte[baseurlLen]; url.Slice(0, baseurlLen).CopyTo(baseUrl); - if (baseUrl.Length == _path_Plaintext.Length && baseUrl.StartsWith(_path_Plaintext)) + if (baseUrl.Length == _path_Plaintext.Length && baseUrl[1] == 'p') { type = ActionType.Plaintext; } - else if (baseUrl.Length == _path_Json.Length && baseUrl.StartsWith(_path_Json)) + else if (baseUrl.Length == _path_Json.Length && baseUrl[1] == 'j') { type = ActionType.Json; } diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs index 27c71d43f13..1604195625e 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.db.cs @@ -17,8 +17,8 @@ public async Task db(IStreamWriter stream) try { - var data = await _db.LoadSingleQueryRow(); - stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length); + var data = await DB.LoadSingleQueryRow(); + stream.Write(_jsonResultPreamble.AsSpan()); content.Data = GetContentLengthMemory(stream); GMTDate.Default.Write(stream); stream.WriteSequenceNetStream.StartWriteLength(); diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs index 829c18bd68a..7bb2fc40acb 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.fortunes.cs @@ -21,11 +21,11 @@ static HtmlEncoder CreateHtmlEncoder() return HtmlEncoder.Create(settings); } - private readonly static AsciiString _fortunesTableStart = "Fortunes"; - private readonly static AsciiString _fortunesRowStart = ""; - private readonly static AsciiString _fortunesTableEnd = "
idmessage
"; - private readonly static AsciiString _fortunesColumn = ""; - private readonly static AsciiString _fortunesRowEnd = "
"; + private static ReadOnlySpan _fortunesTableStart => "Fortunes"u8; + private static ReadOnlySpan _fortunesRowStart => ""u8; + private static ReadOnlySpan _fortunesTableEnd => "
idmessage
"u8; + private static ReadOnlySpan _fortunesColumn => ""u8; + private static ReadOnlySpan _fortunesRowEnd => "
"u8; public async Task fortunes(IStreamWriter stream) @@ -34,23 +34,23 @@ public async Task fortunes(IStreamWriter stream) try { - var data = await this._db.LoadFortunesRows(); + var data = await DB.LoadFortunesRows(); - stream.Write(_HtmlResultPreamble.Data, 0, _HtmlResultPreamble.Length); + stream.Write(_HtmlResultPreamble); content.Data = GetContentLengthMemory(stream); GMTDate.Default.Write(stream); stream.WriteSequenceNetStream.StartWriteLength(); - stream.Write(_fortunesTableStart.Data, 0, _fortunesTableStart.Length); + stream.Write(_fortunesTableStart); foreach (var item in data) { - stream.Write(_fortunesRowStart.Data, 0, _fortunesRowStart.Length); + stream.Write(_fortunesRowStart); stream.WriteString(item.Id.ToString(CultureInfo.InvariantCulture)); - stream.Write(_fortunesColumn.Data, 0, _fortunesColumn.Length); + stream.Write(_fortunesColumn); stream.WriteString(htmlEncoder.Encode(item.Message)); - stream.Write(_fortunesRowEnd.Data, 0, _fortunesRowEnd.Length); + stream.Write(_fortunesRowEnd); } - stream.Write(_fortunesTableEnd.Data, 0, _fortunesTableEnd.Length); + stream.Write(_fortunesTableEnd); } catch (Exception e_) { diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs index 1bfa2d8863f..4a379e98931 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.json.cs @@ -14,10 +14,14 @@ namespace PlatformBenchmarks public partial class HttpHandler { - + private static ReadOnlySpan _jsonPreamble => + "HTTP/1.1 200 OK\r\n"u8 + + "Server: B\r\n"u8 + + "Content-Type: application/json\r\n"u8 + + "Content-Length: 27\r\n"u8; public void Json(IStreamWriter stream) { - stream.Write(_jsonPreamble.Data, 0, _jsonPreamble.Length); + stream.Write(_jsonPreamble); GMTDate.Default.Write(stream); var jsonWriter = GetJsonWriter(stream); using (var unflush = stream.UnFlush()) @@ -27,7 +31,7 @@ public void Json(IStreamWriter stream) jsonWriter.WriteEndObject(); jsonWriter.Flush(); } - + } } } diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs index a011d52f7f4..fe50d21011d 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.plaintext.cs @@ -2,6 +2,7 @@ using BeetleX.Light.Memory; using System; using System.Collections.Generic; +using System.Data; using System.Text; using System.Threading.Tasks; @@ -9,13 +10,27 @@ namespace PlatformBenchmarks { public partial class HttpHandler { - + private static ReadOnlySpan _plaintextPreamble => + "HTTP/1.1 200 OK\r\n"u8 + + "Server: B\r\n"u8 + + "Content-Type: text/plain\r\n"u8 + + "Content-Length: 13\r\n"u8; + + private static ReadOnlySpan _plainTextBody => "Hello, World!"u8; public void Plaintext(IStreamWriter stream) { - stream.Write(_plaintextPreamble.Data, 0, _plaintextPreamble.Length); - GMTDate.Default.Write(stream); - stream.Write(_result_plaintext.Data, 0, _result_plaintext.Length); + Span data = stream.WriteSequenceNetStream.GetWriteSpan(256); + var timedata = GMTDate.Default.DATE; + _plaintextPreamble.CopyTo(data); + data = data.Slice(_plaintextPreamble.Length); + timedata.Span.CopyTo(data); + data = data.Slice(timedata.Length); + _plainTextBody.CopyTo(data); + //stream.Write(_plaintextPreamble.AsSpan()); + //GMTDate.Default.Write(stream); + //stream.Write(_result_plaintext.Data.AsSpan()); + stream.WriteSequenceNetStream.WriteAdvance(_plaintextPreamble.Length + timedata.Length + _plainTextBody.Length); } } } diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs index 53eef8a31fb..4e7039176dd 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.queries.cs @@ -31,7 +31,7 @@ public async ValueTask queries(string queryString, IStreamWriter stream) ContentLengthMemory content = new ContentLengthMemory(); try { - var data = await _db.LoadMultipleQueriesRows(count); + var data = await DB.LoadMultipleQueriesRows(count); stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length); content.Data = GetContentLengthMemory(stream); GMTDate.Default.Write(stream); diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs index 255a430c070..99d938f32a5 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpHandler.updates.cs @@ -32,7 +32,7 @@ public async ValueTask updates(string queryString, IStreamWriter stream) ContentLengthMemory content = new ContentLengthMemory(); try { - var data = await _db.LoadMultipleUpdatesRows(count); + var data = await DB.LoadMultipleUpdatesRows(count); stream.Write(_jsonResultPreamble.Data, 0, _jsonResultPreamble.Length); content.Data = GetContentLengthMemory(stream); diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs index b8ee7c5f495..b6cb8e3a1a0 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/HttpServer.cs @@ -13,13 +13,19 @@ public class HttpServer : IHostedService { private static NetServer _apiServer; - public virtual Task StartAsync(CancellationToken cancellationToken) + public static string _connectionString; + + public virtual async Task StartAsync(CancellationToken cancellationToken) { + _connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=16;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; + //_connectionString = "Server=localhost;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=16;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; ThreadPool.SetMinThreads(Environment.ProcessorCount * 2, Environment.ProcessorCount * 2); - Constants.MemorySegmentMinSize = 1024 * 8; - Constants.MemorySegmentMaxSize = 1024 * 8; + Constants.MemorySegmentMinSize = 1024 * 16; + Constants.MemorySegmentMaxSize = 1024 * 16; Constants.InitMemoryBlock(); - ArraySegment date = GMTDate.Default.DATE; + var date = GMTDate.Default.DATE; + HttpHandler.DB = new RawDb(new ConcurrentRandom(), HttpServer._connectionString); + await HttpHandler.DB.PopulateCache(); _apiServer = new NetServer(); _apiServer.Options.LogLevel = BeetleX.Light.Logs.LogLevel.Error; _apiServer.Options.AddLogOutputHandler(); @@ -30,20 +36,6 @@ public virtual Task StartAsync(CancellationToken cancellationToken) _apiServer.Start(); - if (!Program.UpDB) - { - RawDb._connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; - //RawDb._connectionString = "Server=127.0.0.1;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=256;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3"; - } - else - { - - RawDb._connectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; - //RawDb._connectionString = "Server=127.0.0.1;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=64;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3"; - } - // ApiServer.Log(LogType.Info, null, $"Debug mode [{Program.Debug}]"); - return Task.CompletedTask; - } public virtual Task StopAsync(CancellationToken cancellationToken) diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/PlatformBenchmarks.csproj b/frameworks/CSharp/beetlex/PlatformBenchmarks/PlatformBenchmarks.csproj index 10202a882be..ba5b9d4202d 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/PlatformBenchmarks.csproj +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/PlatformBenchmarks.csproj @@ -8,7 +8,7 @@ - + diff --git a/frameworks/CSharp/beetlex/PlatformBenchmarks/Program.cs b/frameworks/CSharp/beetlex/PlatformBenchmarks/Program.cs index 3819a6c7e1d..ab262ef92a3 100644 --- a/frameworks/CSharp/beetlex/PlatformBenchmarks/Program.cs +++ b/frameworks/CSharp/beetlex/PlatformBenchmarks/Program.cs @@ -17,7 +17,6 @@ public static void Main(string[] args) //Debug = (args != null && args.Length > 0 && args[0] == "debug"); var data = GMTDate.Default.DATE; UpDB = (args != null && args.Length > 0 && args[0] == "updb"); - UpdateCommandsCached.Init(); //HttpServer server = new HttpServer(); //server.StartAsync(default); //Console.ReadLine(); From e33a7759a48caeab2eb51ca8338fe42dcadb4ac6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:50:34 +0000 Subject: [PATCH 11/62] Bump io.undertow:undertow-core in /frameworks/Java/undertow Bumps [io.undertow:undertow-core](https://github.com/undertow-io/undertow) from 2.3.12.Final to 2.3.14.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.3.12.Final...2.3.14.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Java/undertow/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Java/undertow/pom.xml b/frameworks/Java/undertow/pom.xml index 1a0f95afd69..da2a6dd086b 100644 --- a/frameworks/Java/undertow/pom.xml +++ b/frameworks/Java/undertow/pom.xml @@ -20,7 +20,7 @@ 3.2.2 0.9.10 42.7.2 - 2.3.12.Final + 2.3.14.Final From eedd5e5c8acb8a1f8110ddc49576a53a513ce63d Mon Sep 17 00:00:00 2001 From: James Burns Date: Mon, 8 Jul 2024 11:23:27 -0400 Subject: [PATCH 12/62] [Go/echo] Update to pgx (#9134) --- frameworks/Go/echo/echo.dockerfile | 2 +- frameworks/Go/echo/src/go.mod | 8 +++-- frameworks/Go/echo/src/go.sum | 17 +++++++--- frameworks/Go/echo/src/main.go | 51 ++++++++++++++---------------- 4 files changed, 43 insertions(+), 35 deletions(-) diff --git a/frameworks/Go/echo/echo.dockerfile b/frameworks/Go/echo/echo.dockerfile index ccc8c0186d2..ab6a616d4d9 100644 --- a/frameworks/Go/echo/echo.dockerfile +++ b/frameworks/Go/echo/echo.dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.19 +FROM docker.io/golang:1.22 ADD ./src /echo WORKDIR /echo diff --git a/frameworks/Go/echo/src/go.mod b/frameworks/Go/echo/src/go.mod index 63fe7fd1cef..04c940547d5 100644 --- a/frameworks/Go/echo/src/go.mod +++ b/frameworks/Go/echo/src/go.mod @@ -1,13 +1,16 @@ module echo/app -go 1.19 +go 1.22 require ( + github.com/jackc/pgx/v5 v5.6.0 github.com/labstack/echo/v4 v4.9.0 - github.com/lib/pq v1.10.7 ) require ( + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/labstack/gommon v0.3.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect @@ -15,6 +18,7 @@ require ( github.com/valyala/fasttemplate v1.2.1 // indirect golang.org/x/crypto v0.21.0 // indirect golang.org/x/net v0.23.0 // indirect + golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/frameworks/Go/echo/src/go.sum b/frameworks/Go/echo/src/go.sum index 8732c64400d..e607732cf1b 100644 --- a/frameworks/Go/echo/src/go.sum +++ b/frameworks/Go/echo/src/go.sum @@ -1,12 +1,18 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -16,8 +22,9 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= @@ -26,6 +33,8 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -36,5 +45,5 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/frameworks/Go/echo/src/main.go b/frameworks/Go/echo/src/main.go index ed999f215c0..4642ee2f5b1 100644 --- a/frameworks/Go/echo/src/main.go +++ b/frameworks/Go/echo/src/main.go @@ -1,9 +1,11 @@ package main import ( - "database/sql" + "context" "encoding/json" "fmt" + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" "html/template" "io" "log" @@ -13,7 +15,6 @@ import ( "strconv" "github.com/labstack/echo/v4" - _ "github.com/lib/pq" ) type ( @@ -79,10 +80,7 @@ const ( var ( // Database - db *sql.DB - worldSelectStmt *sql.Stmt - worldUpdateStmt *sql.Stmt - fortuneSelectStmt *sql.Stmt + db *pgxpool.Pool // Template Template = &StdTemplate{ @@ -120,8 +118,9 @@ func (h *handler) json() echo.HandlerFunc { // Test 2: Single database query func (h *handler) db() echo.HandlerFunc { return func(c echo.Context) error { + ctx := c.Request().Context() world := new(World) - if err := fetchRandomWorld(world); err != nil { + if err := fetchRandomWorld(ctx, world); err != nil { return err } @@ -134,10 +133,11 @@ func (h *handler) db() echo.HandlerFunc { // Test 3: Multiple database queries func (h *handler) queries() echo.HandlerFunc { return func(c echo.Context) error { + ctx := c.Request().Context() n := getQueryCount(c.QueryParam("n")) worlds := make([]World, n) for i := 0; i < n; i++ { - if err := fetchRandomWorld(&worlds[i]); err != nil { + if err := fetchRandomWorld(ctx, &worlds[i]); err != nil { return err } } @@ -151,7 +151,8 @@ func (h *handler) queries() echo.HandlerFunc { // Test 4: Fortunes func (h *handler) fortunes() echo.HandlerFunc { return func(c echo.Context) error { - rows, err := fortuneSelectStmt.Query() + ctx := c.Request().Context() + rows, err := db.Query(ctx, fortuneSelect) if err != nil { return fmt.Errorf("Error preparing statement: %v", err) } @@ -172,18 +173,19 @@ func (h *handler) fortunes() echo.HandlerFunc { // Test 5: Database updates func (h *handler) updates() echo.HandlerFunc { return func(c echo.Context) error { + ctx := c.Request().Context() n := getQueryCount(c.QueryParam("n")) worlds := make([]World, n) for i := 0; i < n; i++ { // Fetch and modify w := &worlds[i] - if err := fetchRandomWorld(&worlds[i]); err != nil { + if err := fetchRandomWorld(ctx, &worlds[i]); err != nil { return err } w.RandomNumber = uint16(randomWorldNum()) // Update - if _, err := worldUpdateStmt.Exec(w.RandomNumber, w.ID); err != nil { + if _, err := db.Exec(ctx, worldUpdate, w.RandomNumber, w.ID); err != nil { return fmt.Errorf("Error updating world row: %v", err) } } @@ -221,9 +223,9 @@ func (h *handler) plaintext() echo.HandlerFunc { } } -func fetchRandomWorld(w *World) error { +func fetchRandomWorld(ctx context.Context, w *World) error { n := randomWorldNum() - return worldSelectStmt.QueryRow(n).Scan(&w.ID, &w.RandomNumber) + return db.QueryRow(ctx, worldSelect, n).Scan(&w.ID, &w.RandomNumber) } func randomWorldNum() int { @@ -241,7 +243,7 @@ func getQueryCount(q string) int { return n } -func fetchFortunes(rows *sql.Rows) (Fortunes, error) { +func fetchFortunes(rows pgx.Rows) (Fortunes, error) { fortunes := make(Fortunes, 0) for rows.Next() { // Fetch rows f := new(Fortune) @@ -267,24 +269,17 @@ func InitPostgres() { host := "tfb-database" var err error - db, err = sql.Open("postgres", fmt.Sprintf(connectionString, host)) - if err != nil { - log.Fatalf("Error opening database: %v", err) - } - db.SetMaxIdleConns(maxConnections) - db.SetMaxOpenConns(maxConnections) - worldSelectStmt, err = db.Prepare(worldSelect) + dbCfg, err := pgxpool.ParseConfig(fmt.Sprintf(connectionString, host)) if err != nil { - log.Fatal(err) + log.Fatalf("Error reading database connection string: %v", err) } - worldUpdateStmt, err = db.Prepare(worldUpdate) - if err != nil { - log.Fatal(err) - } - fortuneSelectStmt, err = db.Prepare(fortuneSelect) + dbCfg.MaxConns = maxConnections + dbCfg.MinConns = maxConnections + + db, err = pgxpool.NewWithConfig(context.Background(), dbCfg) if err != nil { - log.Fatal(err) + log.Fatalf("Error opening database: %v", err) } } From b0c5935e9b518af59d1e02f3110555f9d3770a40 Mon Sep 17 00:00:00 2001 From: Xudong Huang Date: Mon, 8 Jul 2024 23:23:39 +0800 Subject: [PATCH 13/62] [Rust|may-minihttp] update may_postgres (#9150) --- frameworks/Rust/may-minihttp/Cargo.toml | 2 +- frameworks/Rust/may-minihttp/may-minihttp.dockerfile | 2 +- frameworks/Rust/may-minihttp/src/main.rs | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/frameworks/Rust/may-minihttp/Cargo.toml b/frameworks/Rust/may-minihttp/Cargo.toml index 019aaf898a2..9fc7760ff8e 100644 --- a/frameworks/Rust/may-minihttp/Cargo.toml +++ b/frameworks/Rust/may-minihttp/Cargo.toml @@ -19,7 +19,7 @@ buf-min = { version = "0.7", features = ["bytes"] } may = { version = "0.3", default-features = false } may_minihttp = { version = "0.1", default-features = false } -may_postgres = { git = "https://github.com/Xudong-Huang/may_postgres.git", rev = "5ea3fb9", default-features = false } +may_postgres = { git = "https://github.com/Xudong-Huang/may_postgres.git", rev = "917ed78", default-features = false } [profile.release] opt-level = 3 diff --git a/frameworks/Rust/may-minihttp/may-minihttp.dockerfile b/frameworks/Rust/may-minihttp/may-minihttp.dockerfile index 0ddda28e3eb..160e563ac2c 100644 --- a/frameworks/Rust/may-minihttp/may-minihttp.dockerfile +++ b/frameworks/Rust/may-minihttp/may-minihttp.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.78 +FROM rust:1.79 RUN apt-get update -yqq && apt-get install -yqq cmake g++ diff --git a/frameworks/Rust/may-minihttp/src/main.rs b/frameworks/Rust/may-minihttp/src/main.rs index f6a817031c3..33b410b1c0f 100644 --- a/frameworks/Rust/may-minihttp/src/main.rs +++ b/frameworks/Rust/may-minihttp/src/main.rs @@ -49,7 +49,7 @@ struct PgConnectionPool { impl PgConnectionPool { fn new(db_url: &'static str, size: usize) -> PgConnectionPool { let clients = (0..size) - .map(|_| std::thread::spawn(move || PgConnection::new(db_url))) + .map(|_| may::go!(move || PgConnection::new(db_url))) .collect::>(); let mut clients: Vec<_> = clients.into_iter().map(|t| t.join().unwrap()).collect(); clients.sort_by(|a, b| (a.client.id() % size).cmp(&(b.client.id() % size))); @@ -59,6 +59,7 @@ impl PgConnectionPool { fn get_connection(&self, id: usize) -> PgConnection { let len = self.clients.len(); let connection = &self.clients[id % len]; + // assert_eq!(connection.client.id() % len, id % len); PgConnection { client: connection.client.clone(), statement: connection.statement.clone(), @@ -282,7 +283,7 @@ impl HttpServiceFactory for HttpServer { fn main() { may::config().set_pool_capacity(1000).set_stack_size(0x1000); - println!("Starting http server: 127.0.0.1:8080"); + println!("Starting http server: 0.0.0.1:8080"); let server = HttpServer { db_pool: PgConnectionPool::new( "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world", From 0940648a225b7f988034e980731b23fbf6d652da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:25:09 -0700 Subject: [PATCH 14/62] Bump mysql2 from 3.9.7 to 3.9.8 in /frameworks/JavaScript/spliffy (#9138) Bumps [mysql2](https://github.com/sidorares/node-mysql2) from 3.9.7 to 3.9.8. - [Release notes](https://github.com/sidorares/node-mysql2/releases) - [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md) - [Commits](https://github.com/sidorares/node-mysql2/compare/v3.9.7...v3.9.8) --- updated-dependencies: - dependency-name: mysql2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frameworks/JavaScript/spliffy/package-lock.json | 6 +++--- frameworks/JavaScript/spliffy/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/JavaScript/spliffy/package-lock.json b/frameworks/JavaScript/spliffy/package-lock.json index db22f966f30..40b146ce31c 100644 --- a/frameworks/JavaScript/spliffy/package-lock.json +++ b/frameworks/JavaScript/spliffy/package-lock.json @@ -1189,9 +1189,9 @@ } }, "mysql2": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.7.tgz", - "integrity": "sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==", + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.8.tgz", + "integrity": "sha512-+5JKNjPuks1FNMoy9TYpl77f+5frbTklz7eb3XDwbpsERRLEeXiW2PDEkakYF50UuKU2qwfGnyXpKYvukv8mGA==", "requires": { "denque": "^2.1.0", "generate-function": "^2.3.1", diff --git a/frameworks/JavaScript/spliffy/package.json b/frameworks/JavaScript/spliffy/package.json index bdb6b49aa45..62b2240acf3 100644 --- a/frameworks/JavaScript/spliffy/package.json +++ b/frameworks/JavaScript/spliffy/package.json @@ -6,7 +6,7 @@ "@srfnstack/spliffy": "0.6.1", "html-escaper": "3.0.3", "mongodb": "^4.17.0", - "mysql2": "^3.9.7", + "mysql2": "^3.9.8", "node-cache": "5.1.2", "pg": "8.6.0", "pg-native": "3.0.1" From 172e539de92f0d7d27a16c32466ae064d6710ad8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:25:32 -0700 Subject: [PATCH 15/62] Bump github.com/gofiber/fiber/v2 in /frameworks/Go/fiber/src (#9139) Bumps [github.com/gofiber/fiber/v2](https://github.com/gofiber/fiber) from 2.52.1 to 2.52.5. - [Release notes](https://github.com/gofiber/fiber/releases) - [Commits](https://github.com/gofiber/fiber/compare/v2.52.1...v2.52.5) --- updated-dependencies: - dependency-name: github.com/gofiber/fiber/v2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frameworks/Go/fiber/src/go.mod | 2 +- frameworks/Go/fiber/src/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/Go/fiber/src/go.mod b/frameworks/Go/fiber/src/go.mod index 2372b8f57f7..bb9b8bc5701 100644 --- a/frameworks/Go/fiber/src/go.mod +++ b/frameworks/Go/fiber/src/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/goccy/go-json v0.10.0 - github.com/gofiber/fiber/v2 v2.52.1 + github.com/gofiber/fiber/v2 v2.52.5 github.com/jackc/pgx/v5 v5.5.4 github.com/valyala/quicktemplate v1.7.0 ) diff --git a/frameworks/Go/fiber/src/go.sum b/frameworks/Go/fiber/src/go.sum index 5ae0d5e53e3..1414375d002 100644 --- a/frameworks/Go/fiber/src/go.sum +++ b/frameworks/Go/fiber/src/go.sum @@ -6,8 +6,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlgHI= -github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/fiber/v2 v2.52.5 h1:tWoP1MJQjGEe4GB5TUGOi7P2E0ZMMRx5ZTG4rT+yGMo= +github.com/gofiber/fiber/v2 v2.52.5/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= From 6cb7e7b24f54d4b71c7fc0647be1aa00fd0512d6 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 8 Jul 2024 17:25:49 +0200 Subject: [PATCH 16/62] [rails] Use Ruby 3.4-rc (#9087) --- frameworks/Ruby/rails/rails-mysql.dockerfile | 2 +- frameworks/Ruby/rails/rails.dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/Ruby/rails/rails-mysql.dockerfile b/frameworks/Ruby/rails/rails-mysql.dockerfile index 370b08ba493..a93f26b52da 100644 --- a/frameworks/Ruby/rails/rails-mysql.dockerfile +++ b/frameworks/Ruby/rails/rails-mysql.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.3 +FROM ruby:3.4-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server diff --git a/frameworks/Ruby/rails/rails.dockerfile b/frameworks/Ruby/rails/rails.dockerfile index 3e02770b190..9d75f7d359e 100644 --- a/frameworks/Ruby/rails/rails.dockerfile +++ b/frameworks/Ruby/rails/rails.dockerfile @@ -1,4 +1,4 @@ -FROM ruby:3.3 +FROM ruby:3.4-rc RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server From bba72a8b146ad9d772159872f9676818eda12cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kon=C3=B4pka?= Date: Mon, 8 Jul 2024 17:26:18 +0200 Subject: [PATCH 17/62] Update spring tests to current release of spring-boot (#8876) * Update spring-boot to 3.2.4 * Disable open-in-view globally for all tests open-in-view is unfortunately enabled by default for historical reasons, see https://github.com/spring-projects/spring-boot/issues/7107 This significantly improves performance for requests where db connection is not needed at all, i.e. json & plaintext db ~3% improvement json ~17% improvement query ~no change update ~no change fortune ~5% improvement plaintext ~29% improvement * Make spring-webflux tests work again Replaces old milestone version of spring boot with current release 3.2.5 Also replaces ParalllelGC with default one, i.e. G1GC * Update spring-boot to v3.3.0 * Update to java 21 * Enable virtual threads * Fix excessive number of queries in JPA tests ... query and follow up update statement must be enclosed in a transaction --- .../Java/spring-webflux/benchmark_config.json | 15 ++-- frameworks/Java/spring-webflux/pom.xml | 88 +++---------------- .../spring-webflux-jdbc.dockerfile | 6 +- .../spring-webflux-mongo.dockerfile | 6 +- .../spring-webflux-pgclient.dockerfile | 6 +- .../spring-webflux-rxjdbc.dockerfile | 6 +- .../spring-webflux/spring-webflux.dockerfile | 6 +- .../src/main/java/benchmark/App.java | 15 ++-- .../java/benchmark/config/JdbcConfig.java | 2 +- .../java/benchmark/config/PgClientConfig.java | 4 +- .../java/benchmark/config/R2dbcConfig.java | 6 +- .../benchmark/config/ReactiveMongoConfig.java | 3 +- .../java/benchmark/config/RxJdbcConfig.java | 8 +- .../repository/R2dbcDbRepository.java | 14 ++- .../java/benchmark/web/WebfluxRouter.java | 2 +- .../src/main/resources/application.yml | 48 ++++++++-- frameworks/Java/spring/pom.xml | 3 +- frameworks/Java/spring/spring-jpa.dockerfile | 23 +---- .../Java/spring/spring-mongo.dockerfile | 23 +---- frameworks/Java/spring/spring.dockerfile | 25 +----- .../Java/spring/src/main/java/hello/App.java | 2 +- .../main/java/hello/UpdateWorldService.java | 9 ++ .../java/hello/UpdateWorldServiceImpl.java | 42 +++++++++ .../hello/controller/HelloController.java | 31 +++---- .../spring/src/main/resources/application.yml | 6 +- 25 files changed, 171 insertions(+), 228 deletions(-) create mode 100644 frameworks/Java/spring/src/main/java/hello/UpdateWorldService.java create mode 100644 frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java diff --git a/frameworks/Java/spring-webflux/benchmark_config.json b/frameworks/Java/spring-webflux/benchmark_config.json index e5c13f8e292..396e9e22a1c 100644 --- a/frameworks/Java/spring-webflux/benchmark_config.json +++ b/frameworks/Java/spring-webflux/benchmark_config.json @@ -20,8 +20,7 @@ "database_os": "Linux", "display_name": "spring-webflux-r2dbc", "notes": "", - "versus": "spring", - "tags": ["broken"] + "versus": "spring" }, "mongo": { "db_url": "/db", @@ -41,8 +40,7 @@ "database_os": "Linux", "display_name": "spring-webflux-mongo", "notes": "", - "versus": "spring", - "tags": ["broken"] + "versus": "spring" }, "pgclient": { "db_url": "/db", @@ -63,8 +61,7 @@ "database_os": "Linux", "display_name": "spring-webflux-pgclient", "notes": "", - "versus": "spring", - "tags": ["broken"] + "versus": "spring" }, "rxjdbc": { "db_url": "/db", @@ -85,8 +82,7 @@ "database_os": "Linux", "display_name": "spring-webflux-rxjdbc", "notes": "", - "versus": "spring", - "tags": ["broken"] + "versus": "spring" }, "jdbc": { "db_url": "/db", @@ -107,8 +103,7 @@ "database_os": "Linux", "display_name": "spring-webflux-jdbc", "notes": "", - "versus": "spring", - "tags": ["broken"] + "versus": "spring" } }] } diff --git a/frameworks/Java/spring-webflux/pom.xml b/frameworks/Java/spring-webflux/pom.xml index 01d32c261c0..bec59f53b95 100644 --- a/frameworks/Java/spring-webflux/pom.xml +++ b/frameworks/Java/spring-webflux/pom.xml @@ -13,19 +13,14 @@ org.springframework.boot spring-boot-starter-parent - 2.2.0.M2 + 3.3.0 - 11 - 11 + 17 UTF-8 - 1.0.0.M2 - 42.7.2 0.11.4 - 0.2.4 - 1.0.0.M7 - 1.0.0.BUILD-SNAPSHOT + 0.2.14 @@ -48,7 +43,6 @@ org.postgresql postgresql - ${postgresql.version} io.reactiverse @@ -61,86 +55,25 @@ ${rxjava2-jdbc.version} - - io.r2dbc - r2dbc-postgresql - ${r2dbc-postgresql.version} - + + org.postgresql + r2dbc-postgresql + io.r2dbc r2dbc-pool - ${r2dbc-pool.version} org.springframework.data spring-data-r2dbc - ${spring-data-r2dbc.version} - - - - org.springframework - spring-tx - - - org.springframework - spring-context - - - org.springframework - spring-core - - - org.springframework - spring-beans - - - - - org.springframework - spring-tx - 5.2.0.M2 - org.springframework - spring-context - 5.2.22.BUILD-SNAPSHOT + org.springframework.boot + spring-boot-configuration-processor + true - - org.springframework - spring-core - 5.2.24.RELEASE - - - org.springframework - spring-beans - 5.2.22.BUILD-SNAPSHOT - - - - - spring-libs-snapshot - Spring Snapshots - https://repo.spring.io/libs-snapshot - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - - - spring-libs-snapshot - Spring Snapshots - https://repo.spring.io/libs-snapshot - - - ${project.artifactId} @@ -151,7 +84,6 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.0 false diff --git a/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile index 89f1ba40f89..7c1daea95f3 100644 --- a/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.8.5-openjdk-17-slim as maven +FROM maven:3.9.6-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:17.0-jdk-slim +FROM eclipse-temurin:21.0.3_9-jre-jammy WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc,postgres"] +CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile index 95d24ac6003..d26a7bda983 100644 --- a/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.8.5-openjdk-17-slim as maven +FROM maven:3.9.6-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:17.0-jdk-slim +FROM eclipse-temurin:21.0.3_9-jre-jammy WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=mongo"] +CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=mongo"] diff --git a/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile index 0c03140d05a..2bf38ec11e0 100644 --- a/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.8.5-openjdk-17-slim as maven +FROM maven:3.9.6-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:17.0-jdk-slim +FROM eclipse-temurin:21.0.3_9-jre-jammy WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=pgclient,postgres"] +CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=pgclient,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile index 05aacc1a8f1..0e1edfb74a9 100644 --- a/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.8.5-openjdk-17-slim as maven +FROM maven:3.9.6-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:17.0-jdk-slim +FROM eclipse-temurin:21.0.3_9-jre-jammy WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=rxjdbc,postgres"] +CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=rxjdbc,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux.dockerfile b/frameworks/Java/spring-webflux/spring-webflux.dockerfile index 3d41fc1ecbe..504fb71cfae 100644 --- a/frameworks/Java/spring-webflux/spring-webflux.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.8.5-openjdk-17-slim as maven +FROM maven:3.9.6-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:17.0-jdk-slim +FROM eclipse-temurin:21.0.3_9-jre-jammy WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=r2dbc,postgres"] +CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=r2dbc,postgres"] diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java index e33025461c6..9fa3f318361 100755 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java @@ -1,10 +1,10 @@ package benchmark; +import java.util.concurrent.Executors; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.reactive.result.view.MustacheViewResolver; import org.springframework.context.annotation.Bean; @@ -12,12 +12,11 @@ import org.springframework.web.reactive.config.EnableWebFlux; import org.springframework.web.reactive.config.ViewResolverRegistry; import org.springframework.web.reactive.config.WebFluxConfigurer; + import reactor.core.scheduler.Scheduler; import reactor.core.scheduler.Schedulers; -import java.util.concurrent.Executors; - -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class }) +@SpringBootApplication @EnableWebFlux @EnableScheduling @EnableConfigurationProperties @@ -31,17 +30,17 @@ public static void main(String[] args) { } @Bean - public ServerFilter serverFilter() { + ServerFilter serverFilter() { return new ServerFilter(); } @Bean - public DateHandler dateHandler() { + DateHandler dateHandler() { return new DateHandler(); } @Bean - public Scheduler ioScheduler() { + Scheduler ioScheduler() { return Schedulers.fromExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2)); } diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java index cd97d6e9708..d99729490a4 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java @@ -13,7 +13,7 @@ public class JdbcConfig { @Bean - public DataSource datasource(DataSourceProperties dataSourceProperties) { + DataSource datasource(DataSourceProperties dataSourceProperties) { HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); dataSource.setMaximumPoolSize(Runtime.getRuntime().availableProcessors() * 2); diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java index ebcbc732d67..9ebf6db60c9 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java @@ -24,12 +24,12 @@ public class PgClientConfig { private String password; @Bean - public Vertx vertx() { + Vertx vertx() { return Vertx.vertx(); } @Bean - public PgClients pgClients(Vertx vertx) { + PgClients pgClients(Vertx vertx) { List clients = new ArrayList<>(); for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) { diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java index 60e006cc80f..5a0de452252 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java @@ -9,7 +9,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import org.springframework.data.r2dbc.core.DatabaseClient; +import org.springframework.r2dbc.core.DatabaseClient; import static io.r2dbc.spi.ConnectionFactoryOptions.*; @@ -44,7 +44,7 @@ public void setPassword(String password) { } @Bean - public ConnectionFactory connectionFactory() { + ConnectionFactory connectionFactory() { return ConnectionFactories.get(ConnectionFactoryOptions.builder() .option(DRIVER,"pool") .option(PROTOCOL,"postgresql") @@ -57,7 +57,7 @@ public ConnectionFactory connectionFactory() { } @Bean - public DatabaseClient databaseClient(ConnectionFactory connectionFactory) { + DatabaseClient databaseClient(ConnectionFactory connectionFactory) { return DatabaseClient.create(connectionFactory); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java index ee80f0fd87b..e12178be400 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java @@ -19,6 +19,7 @@ public class ReactiveMongoConfig extends AbstractReactiveMongoConfiguration { private String url; private String name; + @Override @Bean public MongoClient reactiveMongoClient() { LoggerFactory.getLogger(getClass()).info("Connecting to mongo url: {}/{}", url, name); @@ -31,7 +32,7 @@ protected String getDatabaseName() { } @Bean - public ReactiveMongoTemplate reactiveMongoTemplate() { + ReactiveMongoTemplate reactiveMongoTemplate() { return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName()); } diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java index 23b7d200cca..f4f5916252d 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java @@ -9,21 +9,17 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; -import java.sql.SQLException; - @Configuration @Profile("rxjdbc") public class RxJdbcConfig { @Bean - public Database database(DataSourceProperties dsProps) throws SQLException { + Database database(DataSourceProperties dsProps) { NonBlockingConnectionPool pool = Pools.nonBlocking() .maxPoolSize(Runtime.getRuntime().availableProcessors() * 2) .connectionProvider(ConnectionProvider.from(dsProps.getUrl(), dsProps.getUsername(), dsProps.getPassword())) .build(); - Database db = Database.from(pool); - - return db; + return Database.from(pool); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java index a6979ffb058..e5915fc05d7 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java @@ -3,7 +3,7 @@ import benchmark.model.Fortune; import benchmark.model.World; import org.springframework.context.annotation.Profile; -import org.springframework.data.r2dbc.core.DatabaseClient; +import org.springframework.r2dbc.core.DatabaseClient; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -19,17 +19,16 @@ public R2dbcDbRepository(DatabaseClient databaseClient) { @Override public Mono getWorld(int id) { - return databaseClient.execute() + return databaseClient .sql("SELECT id, randomnumber FROM world WHERE id = $1") .bind("$1", id) - .as(World.class) - .fetch() + .map((row, rowMetaData) -> new World(row.get("id", Integer.class), row.get("randomnumber", Integer.class))) .first(); } public Mono updateWorld(World world) { - return databaseClient.execute() + return databaseClient .sql("UPDATE world SET randomnumber=$2 WHERE id = $1") .bind("$1", world.id) .bind("$2", world.randomnumber) @@ -47,10 +46,9 @@ public Mono findAndUpdateWorld(int id, int randomNumber) { @Override public Flux fortunes() { - return databaseClient.execute() + return databaseClient .sql("SELECT id, message FROM fortune") - .as(Fortune.class) - .fetch() + .map((row, rowMetaData) -> new Fortune(row.get("id", Integer.class), row.get("message", String.class))) .all(); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java index b4dfb9be319..7d1ad9c881a 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java @@ -12,7 +12,7 @@ public class WebfluxRouter { @Bean - public RouterFunction route(WebfluxHandler handler) { + RouterFunction route(WebfluxHandler handler) { return RouterFunctions .route( GET("/plaintext"), diff --git a/frameworks/Java/spring-webflux/src/main/resources/application.yml b/frameworks/Java/spring-webflux/src/main/resources/application.yml index d45387cecde..d315f4353ee 100755 --- a/frameworks/Java/spring-webflux/src/main/resources/application.yml +++ b/frameworks/Java/spring-webflux/src/main/resources/application.yml @@ -1,6 +1,12 @@ +spring: + jpa: + open-in-view: false + --- spring: - profiles: postgres + config: + activate: + on-profile: postgres datasource: url: jdbc:postgresql://${database.host}:${database.port}/${database.name} username: ${database.username} @@ -15,23 +21,53 @@ database: --- spring: - profiles: jdbc + config: + activate: + on-profile: jdbc + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration + - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration --- spring: - profiles: pgclient + config: + activate: + on-profile: pgclient + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration + - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration --- spring: - profiles: rxjdbc + config: + activate: + on-profile: rxjdbc + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration + - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration --- spring: - profiles: r2dbc + config: + activate: + on-profile: r2dbc + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration --- spring: - profiles: mongo + config: + activate: + on-profile: mongo + autoconfigure: + exclude: + - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration database: url: mongodb://tfb-database:27017/?waitQueueMultiple=200 diff --git a/frameworks/Java/spring/pom.xml b/frameworks/Java/spring/pom.xml index b646277a3b0..4e390ebc4f6 100644 --- a/frameworks/Java/spring/pom.xml +++ b/frameworks/Java/spring/pom.xml @@ -11,12 +11,11 @@ org.springframework.boot spring-boot-starter-parent - 3.0.0 + 3.3.0 17 - 42.5.1 diff --git a/frameworks/Java/spring/spring-jpa.dockerfile b/frameworks/Java/spring/spring-jpa.dockerfile index 4c197667a24..4af1b98a73f 100644 --- a/frameworks/Java/spring/spring-jpa.dockerfile +++ b/frameworks/Java/spring/spring-jpa.dockerfile @@ -1,30 +1,11 @@ -FROM eclipse-temurin:17 as jre-build - -# Create a custom Java runtime -RUN $JAVA_HOME/bin/jlink \ - --add-modules ALL-MODULE-PATH \ - --strip-debug \ - --no-man-pages \ - --no-header-files \ - --compress=2 \ - --output /javaruntime - -FROM maven:3.8.5-openjdk-17-slim as maven -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM maven:3.9.6-eclipse-temurin-21 as maven RUN mvn -version WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM debian:bullseye-slim -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM eclipse-temurin:21.0.3_9-jre-jammy RUN java -version WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar diff --git a/frameworks/Java/spring/spring-mongo.dockerfile b/frameworks/Java/spring/spring-mongo.dockerfile index 3672481ca61..4fa82a28d5d 100644 --- a/frameworks/Java/spring/spring-mongo.dockerfile +++ b/frameworks/Java/spring/spring-mongo.dockerfile @@ -1,30 +1,11 @@ -FROM eclipse-temurin:17 as jre-build - -# Create a custom Java runtime -RUN $JAVA_HOME/bin/jlink \ - --add-modules ALL-MODULE-PATH \ - --strip-debug \ - --no-man-pages \ - --no-header-files \ - --compress=2 \ - --output /javaruntime - -FROM maven:3.8.5-openjdk-17-slim as maven -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM maven:3.9.6-eclipse-temurin-21 as maven RUN mvn -version WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM debian:bullseye-slim -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM eclipse-temurin:21.0.3_9-jre-jammy RUN java -version WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar diff --git a/frameworks/Java/spring/spring.dockerfile b/frameworks/Java/spring/spring.dockerfile index a06133e8c45..f6f5145477f 100644 --- a/frameworks/Java/spring/spring.dockerfile +++ b/frameworks/Java/spring/spring.dockerfile @@ -1,34 +1,15 @@ -FROM eclipse-temurin:17 as jre-build - -# Create a custom Java runtime -RUN $JAVA_HOME/bin/jlink \ - --add-modules ALL-MODULE-PATH \ - --strip-debug \ - --no-man-pages \ - --no-header-files \ - --compress=2 \ - --output /javaruntime - -FROM maven:3.8.5-openjdk-17-slim as maven -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM maven:3.9.6-eclipse-temurin-21 as maven RUN mvn -version WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM debian:bullseye-slim -ENV JAVA_HOME=/opt/java/openjdk -ENV PATH "${JAVA_HOME}/bin:${PATH}" -COPY --from=jre-build /javaruntime $JAVA_HOME - +FROM eclipse-temurin:21.0.3_9-jre-jammy RUN java -version WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseG1GC", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc"] +CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc"] diff --git a/frameworks/Java/spring/src/main/java/hello/App.java b/frameworks/Java/spring/src/main/java/hello/App.java index e8e93b65902..0ab1327f8c4 100644 --- a/frameworks/Java/spring/src/main/java/hello/App.java +++ b/frameworks/Java/spring/src/main/java/hello/App.java @@ -28,7 +28,7 @@ public void runAfterStartup() { @Bean @Profile({ "jdbc", "jpa" }) - public DataSource datasource(DataSourceProperties dataSourceProperties) { + DataSource datasource(DataSourceProperties dataSourceProperties) { HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class) .build(); dataSource.setMaximumPoolSize(Runtime.getRuntime().availableProcessors() * 2); diff --git a/frameworks/Java/spring/src/main/java/hello/UpdateWorldService.java b/frameworks/Java/spring/src/main/java/hello/UpdateWorldService.java new file mode 100644 index 00000000000..11c6568c076 --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/UpdateWorldService.java @@ -0,0 +1,9 @@ +package hello; + +import hello.model.World; + +public interface UpdateWorldService { + + World updateWorld(int worldId); + +} diff --git a/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java b/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java new file mode 100644 index 00000000000..b59680aef5c --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java @@ -0,0 +1,42 @@ +package hello; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import hello.controller.HelloController; +import hello.model.World; +import hello.repository.DbRepository; + +@Service +public class UpdateWorldServiceImpl implements UpdateWorldService { + + private DbRepository dbRepository; + + public UpdateWorldServiceImpl(DbRepository dbRepository) { + this.dbRepository = dbRepository; + } + + @Override + @Transactional + public World updateWorld(int worldId) { + var world = dbRepository.getWorld(worldId); + // Ensure that the new random number is not equal to the old one. + // That would cause the JPA-based implementation to avoid sending the + // UPDATE query to the database, which would violate the test + // requirements. + + // Locally the records doesn't exist, maybe in the yours is ok but we need to + // make this check + if (world == null) { + return null; + } + + int newRandomNumber; + do { + newRandomNumber = HelloController.randomWorldNumber(); + } while (newRandomNumber == world.randomnumber); + + return dbRepository.updateWorld(world, newRandomNumber); + } + +} diff --git a/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java b/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java index 6046a2e7426..3c891567942 100644 --- a/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java +++ b/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java @@ -13,6 +13,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import hello.UpdateWorldService; import hello.model.Fortune; import hello.model.World; import hello.repository.DbRepository; @@ -21,9 +22,13 @@ public final class HelloController { private DbRepository dbRepository; + private UpdateWorldService updateWorldService; - public HelloController(DbRepository dbRepository) { + public HelloController( + DbRepository dbRepository, + UpdateWorldService updateWorldService) { this.dbRepository = dbRepository; + this.updateWorldService = updateWorldService; } @GetMapping(value = "/plaintext") @@ -54,25 +59,9 @@ World[] queries(HttpServletResponse response, @RequestParam(required = false) St @GetMapping("/updates") World[] updates(HttpServletResponse response, @RequestParam(required = false) String queries) { response.setContentType(MediaType.APPLICATION_JSON_VALUE); - return randomWorldNumbers().mapToObj(dbRepository::getWorld).map(world -> { - // Ensure that the new random number is not equal to the old one. - // That would cause the JPA-based implementation to avoid sending the - // UPDATE query to the database, which would violate the test - // requirements. - - // Locally the records doesn't exist, maybe in the yours is ok but we need to - // make this check - if (world == null) { - return null; - } - - int newRandomNumber; - do { - newRandomNumber = randomWorldNumber(); - } while (newRandomNumber == world.randomnumber); - - return dbRepository.updateWorld(world, newRandomNumber); - }).limit(parseQueryCount(queries)).toArray(World[]::new); + return randomWorldNumbers() + .mapToObj(id -> updateWorldService.updateWorld(id)) + .limit(parseQueryCount(queries)).toArray(World[]::new); } @GetMapping("/fortunes") @@ -89,7 +78,7 @@ List fortunes(HttpServletResponse response) { private static final int MIN_WORLD_NUMBER = 1; private static final int MAX_WORLD_NUMBER_PLUS_ONE = 10_001; - private static int randomWorldNumber() { + public static int randomWorldNumber() { return ThreadLocalRandom.current().nextInt(MIN_WORLD_NUMBER, MAX_WORLD_NUMBER_PLUS_ONE); } diff --git a/frameworks/Java/spring/src/main/resources/application.yml b/frameworks/Java/spring/src/main/resources/application.yml index 0f411d6d8e9..42c14602858 100644 --- a/frameworks/Java/spring/src/main/resources/application.yml +++ b/frameworks/Java/spring/src/main/resources/application.yml @@ -1,5 +1,10 @@ --- spring: + threads: + virtual: + enabled: true + jpa: + open-in-view: false config: activate: on-profile: jdbc,jpa @@ -22,7 +27,6 @@ spring: on-profile: jpa jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect - open-in-view: false --- spring: From bd015859fa65e3223c928d397db2c832865ae1bf Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 8 Jul 2024 17:26:41 +0200 Subject: [PATCH 18/62] [ruby|rack-sequel] Use OJ for faster json serialization. (#9147) --- frameworks/Ruby/rack-sequel/Gemfile | 1 + frameworks/Ruby/rack-sequel/hello_world.rb | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/frameworks/Ruby/rack-sequel/Gemfile b/frameworks/Ruby/rack-sequel/Gemfile index fb4b4ad65d8..22e0dd418b8 100644 --- a/frameworks/Ruby/rack-sequel/Gemfile +++ b/frameworks/Ruby/rack-sequel/Gemfile @@ -1,6 +1,7 @@ source 'https://rubygems.org' gem 'json', '~> 2.0' +gem 'oj', '~> 3.14', platforms: %i[ruby mswin] gem 'passenger', '~> 6.0', :platforms=>[:ruby, :mswin], :require=>false gem 'puma', '~> 6.4', :require=>false gem 'sequel', '~> 5.0' diff --git a/frameworks/Ruby/rack-sequel/hello_world.rb b/frameworks/Ruby/rack-sequel/hello_world.rb index d68de1f48d7..6fc3a787975 100644 --- a/frameworks/Ruby/rack-sequel/hello_world.rb +++ b/frameworks/Ruby/rack-sequel/hello_world.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +require 'oj' +Oj.mimic_JSON + # Our Rack application to be executed by rackup class HelloWorld DEFAULT_HEADERS = {}.tap do |h| @@ -91,19 +94,19 @@ def call(env) case env['PATH_INFO'] when '/json' # Test type 1: JSON serialization - [JSON_TYPE, JSON.fast_generate(message: 'Hello, World!')] + [JSON_TYPE, { message: 'Hello, World!' }.to_json] when '/db' # Test type 2: Single database query - [JSON_TYPE, JSON.fast_generate(db)] + [JSON_TYPE, db.to_json] when '/queries' # Test type 3: Multiple database queries - [JSON_TYPE, JSON.fast_generate(queries(env))] + [JSON_TYPE, queries(env).to_json] when '/fortunes' # Test type 4: Fortunes [HTML_TYPE, fortunes] when '/updates' # Test type 5: Database updates - [JSON_TYPE, JSON.fast_generate(updates(env))] + [JSON_TYPE, updates(env).to_json] when '/plaintext' # Test type 6: Plaintext [PLAINTEXT_TYPE, 'Hello, World!'] From 14c71fdc30b0da386a6927ff9d98aa083994fdfc Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 8 Jul 2024 17:26:50 +0200 Subject: [PATCH 19/62] [ruby|sinatra] Use batch update on postgres (#9143) --- frameworks/Ruby/sinatra/Gemfile | 12 ++++++------ frameworks/Ruby/sinatra/boot.rb | 14 ++++++++++++-- frameworks/Ruby/sinatra/hello_world.rb | 25 +++++++++++++------------ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/frameworks/Ruby/sinatra/Gemfile b/frameworks/Ruby/sinatra/Gemfile index 22752eec379..ff34570a2cb 100644 --- a/frameworks/Ruby/sinatra/Gemfile +++ b/frameworks/Ruby/sinatra/Gemfile @@ -1,16 +1,16 @@ source 'https://rubygems.org' -gem 'activerecord', '~> 7.0', :require=>'active_record' +gem 'activerecord', '~> 7.1', require: 'active_record' gem 'oj' -gem 'passenger', '~> 6.0', :platforms=>[:ruby, :mswin], :require=>false -gem 'puma', '~> 6.4', :require=>false -gem 'sinatra', '~> 3.0', :require=>'sinatra/base' -gem 'unicorn', '~> 6.1', :platforms=>[:ruby, :mswin], :require=>false +gem 'passenger', '~> 6.0', platforms: [:ruby, :mswin], require: false +gem 'puma', '~> 6.4', require: false +gem 'sinatra', '~> 3.0', require: 'sinatra/base' +gem 'unicorn', '~> 6.1', platforms: [:ruby, :mswin], require: false group :mysql do gem 'mysql2', '~> 0.5', :platforms=>[:ruby, :mswin] end group :postgresql do - gem 'pg', '~> 1.5', :platforms=>[:ruby, :mswin] + gem 'pg', '~> 1.5', platforms: [:ruby, :mswin] end diff --git a/frameworks/Ruby/sinatra/boot.rb b/frameworks/Ruby/sinatra/boot.rb index 355fc53df74..97fa0c40bdb 100644 --- a/frameworks/Ruby/sinatra/boot.rb +++ b/frameworks/Ruby/sinatra/boot.rb @@ -58,8 +58,18 @@ def connect(dbtype) class World < ActiveRecord::Base self.table_name = name - alias_attribute(:randomnumber, :randomNumber) \ - if connection.adapter_name.downcase.start_with?('mysql') + alias_attribute(:randomNumber, :randomnumber) \ + if connection.adapter_name.downcase.start_with?('postgres') + + if connection.adapter_name.downcase.start_with?('mysql') + def self.upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) + # On MySQL Batch updates verification isn't supported yet by TechEmpower. + # https://github.com/TechEmpower/FrameworkBenchmarks/issues/5983 + attributes.each do |attrs| + where(id: attrs[:id]).update_all(randomNumber: attrs[:randomNumber]) + end + end + end end class Fortune < ActiveRecord::Base diff --git a/frameworks/Ruby/sinatra/hello_world.rb b/frameworks/Ruby/sinatra/hello_world.rb index 90238498ed2..328fa402921 100644 --- a/frameworks/Ruby/sinatra/hello_world.rb +++ b/frameworks/Ruby/sinatra/hello_world.rb @@ -45,7 +45,7 @@ def rand1 # Test type 1: JSON serialization get '/json' do - json :message=>'Hello, World!' + json message: 'Hello, World!' end # Test type 2: Single database query @@ -76,27 +76,28 @@ def rand1 Fortune.all end.to_a @fortunes << Fortune.new( - :id=>0, - :message=>'Additional fortune added at request time.' + id: 0, + message: 'Additional fortune added at request time.' ) @fortunes.sort_by!(&:message) - erb :fortunes, :layout=>true + erb :fortunes, layout: true end # Test type 5: Database updates get '/updates' do worlds = - ActiveRecord::Base.connection_pool.with_connection do - ALL_IDS.sample(bounded_queries).map do |id| - world = World.find(id) - new_value = rand1 - new_value = rand1 while new_value == world.randomnumber - world.update_columns(randomnumber: new_value) - world.attributes + ALL_IDS.sample(bounded_queries).map do |id| + world = ActiveRecord::Base.connection_pool.with_connection do + World.find(id) end + new_value = rand1 + new_value = rand1 until new_value != world.randomNumber + { id: id, randomNumber: new_value } end - + ActiveRecord::Base.connection_pool.with_connection do + World.upsert_all(worlds.sort_by!{_1[:id]}) + end json worlds end From 3661938ab43508bde64f90c2491ab5b774ff9b5a Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 8 Jul 2024 17:27:01 +0200 Subject: [PATCH 20/62] [ruby/rack] Upgrade Rack to latest version (#9140) --- frameworks/Ruby/rack/Gemfile.lock | 60 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/frameworks/Ruby/rack/Gemfile.lock b/frameworks/Ruby/rack/Gemfile.lock index 75e57b3ea0e..0fa04f72580 100644 --- a/frameworks/Ruby/rack/Gemfile.lock +++ b/frameworks/Ruby/rack/Gemfile.lock @@ -2,37 +2,36 @@ GEM remote: https://rubygems.org/ specs: ast (2.4.2) - async (2.11.0) + async (2.12.1) console (~> 1.25, >= 1.25.2) fiber-annotation - io-event (~> 1.5, >= 1.5.1) - timers (~> 4.1) + io-event (~> 1.6, >= 1.6.5) async-container (0.18.2) async (~> 2.10) - async-http (0.66.3) + async-http (0.69.0) async (>= 2.10.2) - async-pool (>= 0.6.1) - io-endpoint (~> 0.10, >= 0.10.3) + async-pool (~> 0.7) + io-endpoint (~> 0.11) io-stream (~> 0.4) - protocol-http (~> 0.26.0) - protocol-http1 (~> 0.19.0) - protocol-http2 (~> 0.17.0) - traces (>= 0.10.0) + protocol-http (~> 0.26) + protocol-http1 (~> 0.19) + protocol-http2 (~> 0.18) + traces (>= 0.10) async-http-cache (0.4.3) async-http (~> 0.56) - async-pool (0.6.1) + async-pool (0.7.0) async (>= 1.25) async-service (0.12.0) async async-container (~> 0.16) bigdecimal (3.1.8) - concurrent-ruby (1.2.3) + concurrent-ruby (1.3.3) connection_pool (2.4.1) console (1.25.2) fiber-annotation fiber-local (~> 1.1) json - falcon (0.47.6) + falcon (0.47.7) async async-container (~> 0.18) async-http (~> 0.66, >= 0.66.3) @@ -47,9 +46,9 @@ GEM fiber-annotation (0.2.0) fiber-local (1.1.0) fiber-storage - fiber-storage (0.1.0) - io-endpoint (0.10.3) - io-event (1.5.1) + fiber-storage (0.1.2) + io-endpoint (0.11.0) + io-event (1.6.5) io-stream (0.4.0) json (2.7.2) kgio (2.11.4) @@ -57,11 +56,11 @@ GEM localhost (1.3.1) mapping (1.1.1) nio4r (2.7.3) - oj (3.16.3) + oj (3.16.4) bigdecimal (>= 3.0) openssl (3.2.0) - parallel (1.24.0) - parser (3.3.1.0) + parallel (1.25.1) + parser (3.3.3.0) ast (~> 2.4.1) racc pg (1.5.6) @@ -69,27 +68,27 @@ GEM console (~> 1.8) samovar (~> 2.1) protocol-hpack (1.4.3) - protocol-http (0.26.5) + protocol-http (0.26.6) protocol-http1 (0.19.1) protocol-http (~> 0.22) - protocol-http2 (0.17.0) + protocol-http2 (0.18.0) protocol-hpack (~> 1.4) protocol-http (~> 0.18) - protocol-rack (0.5.1) + protocol-rack (0.6.0) protocol-http (~> 0.23) rack (>= 1.0) puma (6.4.2) nio4r (~> 2.0) - racc (1.7.3) - rack (3.0.11) + racc (1.8.0) + rack (3.1.6) rack-test (2.1.0) rack (>= 1.3) rainbow (3.1.1) raindrops (0.20.1) - regexp_parser (2.9.1) - rexml (3.2.8) - strscan (>= 3.0.9) - rubocop (1.63.5) + regexp_parser (2.9.2) + rexml (3.3.1) + strscan + rubocop (1.64.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) @@ -106,13 +105,12 @@ GEM samovar (2.3.0) console (~> 1.0) mapping (~> 1.0) - sequel (5.80.0) + sequel (5.82.0) bigdecimal sequel_pg (1.17.1) pg (>= 0.18.0, != 1.2.0) sequel (>= 4.38.0) strscan (3.1.0) - timers (4.3.5) traces (0.11.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) @@ -145,4 +143,4 @@ DEPENDENCIES unicorn (~> 6.1) BUNDLED WITH - 2.4.10 + 2.5.11 From bec7f74cb49b04a8a86d4d46003e9d17205a59fa Mon Sep 17 00:00:00 2001 From: kanarus Date: Tue, 9 Jul 2024 00:27:12 +0900 Subject: [PATCH 21/62] update ohkami to v0.19, dependencies & refactor some (#9120) --- frameworks/Rust/ohkami/Cargo.lock | 22 +++++++++++----------- frameworks/Rust/ohkami/Cargo.toml | 6 +++--- frameworks/Rust/ohkami/README.md | 2 +- frameworks/Rust/ohkami/ohkami.dockerfile | 2 +- frameworks/Rust/ohkami/src/postgres.rs | 9 +++------ 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/frameworks/Rust/ohkami/Cargo.lock b/frameworks/Rust/ohkami/Cargo.lock index b0bc7617d71..95d46009a5b 100644 --- a/frameworks/Rust/ohkami/Cargo.lock +++ b/frameworks/Rust/ohkami/Cargo.lock @@ -770,9 +770,9 @@ dependencies = [ [[package]] name = "ohkami" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d810447a32af4750a45183a4915db5ca4183bb6d44b8e7731e63f627c581d93e" +checksum = "e598d3d323527b920e159d55da2754067a5edfbc0678d60b3886fc379f4637f2" dependencies = [ "byte_reader", "hmac", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "ohkami_framework_benchmarks" -version = "0.18.2" +version = "0.19.0" dependencies = [ "futures-util", "ohkami", @@ -799,9 +799,9 @@ dependencies = [ [[package]] name = "ohkami_lib" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4433e6c4c6c67a72afc306783ca8c641e69c9d171279fcab51f1f0c2d875e121" +checksum = "05fdeee00f86ee850c63a15068f2c2a3aeb6d707d4936f2261ec0e70ff48704b" dependencies = [ "byte_reader", "percent-encoding", @@ -810,9 +810,9 @@ dependencies = [ [[package]] name = "ohkami_macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffed4cd7e8c12a62c077273cb0f0fedf67ca3912488e5de1b325be85ca86bb06" +checksum = "d5fa46d8805dede76dce71f8725d48d655f74e2c702824f7a785257d1cc4dd1b" dependencies = [ "proc-macro2", "quote", @@ -1574,9 +1574,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -1593,9 +1593,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/frameworks/Rust/ohkami/Cargo.toml b/frameworks/Rust/ohkami/Cargo.toml index 8a168f5c413..b6bf50cf97c 100644 --- a/frameworks/Rust/ohkami/Cargo.toml +++ b/frameworks/Rust/ohkami/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "ohkami_framework_benchmarks" -version = "0.18.2" +version = "0.19.0" edition = "2021" authors = ["kanarus "] [dependencies] -ohkami = { version = "=0.18.2", features = ["rt_tokio"] } -tokio = { version = "1.37.0" , features = ["full"] } +ohkami = { version = "=0.19.0", features = ["rt_tokio"] } +tokio = { version = "1.38.0" , features = ["full"] } rand = { version = "0.8.5" , features = ["small_rng"] } sqlx = { version = "0.7.4" , features = ["postgres", "macros", "runtime-tokio-native-tls"] } yarte = { version = "0.15.7" } diff --git a/frameworks/Rust/ohkami/README.md b/frameworks/Rust/ohkami/README.md index 21b85f2cc50..d9fda426ed3 100644 --- a/frameworks/Rust/ohkami/README.md +++ b/frameworks/Rust/ohkami/README.md @@ -1,4 +1,4 @@ -# [ohkami](https://github.com/kana-rus/ohkami) - Intuitive and Declarative Web Framework for Rust +# [Ohkami](https://github.com/kana-rus/ohkami) - Intuitive and Declarative Web Framework for Rust ## Description diff --git a/frameworks/Rust/ohkami/ohkami.dockerfile b/frameworks/Rust/ohkami/ohkami.dockerfile index 97a69dd07ae..b993ec905a5 100644 --- a/frameworks/Rust/ohkami/ohkami.dockerfile +++ b/frameworks/Rust/ohkami/ohkami.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.78-slim-buster +FROM rust:1.79-slim-buster WORKDIR /ohkami_framework_benchmarks ENV DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world diff --git a/frameworks/Rust/ohkami/src/postgres.rs b/frameworks/Rust/ohkami/src/postgres.rs index 7f29317d1ba..e9238d67493 100644 --- a/frameworks/Rust/ohkami/src/postgres.rs +++ b/frameworks/Rust/ohkami/src/postgres.rs @@ -16,16 +16,14 @@ impl Postgres { pub async fn select_random_world(&self) -> World { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - sqlx::query_as( - "SELECT id, randomnumber FROM World WHERE id = $1") + sqlx::query_as("SELECT id, randomnumber FROM World WHERE id = $1") .bind((rng.gen::() % 10_000 + 1) as i32) .fetch_one(&self.0).await .expect("Failed to fetch a world") } pub async fn select_all_fortunes(&self) -> Vec { - sqlx::query_as( - "SELECT id, message FROM Fortune") + sqlx::query_as("SELECT id, message FROM Fortune") .fetch_all(&self.0).await .expect("Failed to fetch fortunes") } @@ -36,8 +34,7 @@ impl Postgres { let selects = FuturesUnordered::new(); for _ in 0..n { selects.push( - sqlx::query_as( - "SELECT id, randomnumber FROM World WHERE id = $1") + sqlx::query_as("SELECT id, randomnumber FROM World WHERE id = $1") .bind((rng.gen::() % 10_000 + 1) as i32) .fetch_one(&self.0) ) From b9ced2e628825736093bc234da171a456c5f88d9 Mon Sep 17 00:00:00 2001 From: Vladimir Shchur Date: Mon, 8 Jul 2024 18:27:45 +0300 Subject: [PATCH 22/62] [F#/Oxpecker] Changed db type from micro-ORM to raw + refactoring (#9118) * [F#/Oxpecker] Switched from Dapper to raw ADO (cherry picked from commit 2f386186a28f7dc502a3d3c7da35211e12d395f0) * [F#/Oxpecker] Refactoring * [F#/Oxpecker] Updated Readme * [F#/Oxpecker] Updated Readme * [F#/Oxpecker] Fixed "versus" field --- frameworks/FSharp/oxpecker/README.md | 11 +- .../FSharp/oxpecker/benchmark_config.json | 4 +- frameworks/FSharp/oxpecker/config.toml | 4 +- frameworks/FSharp/oxpecker/src/App/App.fsproj | 3 +- frameworks/FSharp/oxpecker/src/App/Common.fs | 34 ++++++ frameworks/FSharp/oxpecker/src/App/Db.fs | 104 +++++++++++++++++ frameworks/FSharp/oxpecker/src/App/Program.fs | 109 +++--------------- 7 files changed, 162 insertions(+), 107 deletions(-) create mode 100644 frameworks/FSharp/oxpecker/src/App/Common.fs create mode 100644 frameworks/FSharp/oxpecker/src/App/Db.fs diff --git a/frameworks/FSharp/oxpecker/README.md b/frameworks/FSharp/oxpecker/README.md index ecd2284661d..3d8a00a248a 100644 --- a/frameworks/FSharp/oxpecker/README.md +++ b/frameworks/FSharp/oxpecker/README.md @@ -1,5 +1,5 @@ # Oxpecker Tests on Linux -This includes tests for plaintext, json, and fortunes HTML serialization. +This includes tests for plaintext, json, fortunes, single query, mutliple queries and data updates. ## Infrastructure Software Versions @@ -18,9 +18,6 @@ This includes tests for plaintext, json, and fortunes HTML serialization. **Web Stack** * [Oxpecker](https://github.com/Lanayx/Oxpecker) -* [Dapper](https://github.com/DapperLib/Dapper) -* ASP.NET Core - -## Paths & Source for Tests - -All source code is inside `Program.fs`. +* [Npgsql](https://github.com/npgsql/npgsql) +* [System.Text.Json](https://github.com/dotnet/runtime/tree/main/src/libraries/System.Text.Json) +* ASP.NET Core \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/benchmark_config.json b/frameworks/FSharp/oxpecker/benchmark_config.json index c0df28d86a3..562c9514420 100644 --- a/frameworks/FSharp/oxpecker/benchmark_config.json +++ b/frameworks/FSharp/oxpecker/benchmark_config.json @@ -15,7 +15,7 @@ "database": "Postgres", "framework": "Oxpecker", "language": "F#", - "orm": "Micro", + "orm": "Raw", "platform": ".NET", "flavor": "CoreCLR", "webserver": "Kestrel", @@ -23,7 +23,7 @@ "database_os": "Linux", "display_name": "Oxpecker", "notes": "", - "versus": "aspcore" + "versus": "aspnetcore" } } ] diff --git a/frameworks/FSharp/oxpecker/config.toml b/frameworks/FSharp/oxpecker/config.toml index dd5e34c8b96..75e7f904754 100644 --- a/frameworks/FSharp/oxpecker/config.toml +++ b/frameworks/FSharp/oxpecker/config.toml @@ -13,7 +13,7 @@ classification = "fullstack" database = "Postgres" database_os = "Linux" os = "Linux" -orm = "micro" +orm = "Raw" platform = ".NET" webserver = "Kestrel" -versus = "aspcore" \ No newline at end of file +versus = "aspnetcore" \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/src/App/App.fsproj b/frameworks/FSharp/oxpecker/src/App/App.fsproj index a9e0ad2c0ba..f01c367f95f 100644 --- a/frameworks/FSharp/oxpecker/src/App/App.fsproj +++ b/frameworks/FSharp/oxpecker/src/App/App.fsproj @@ -6,12 +6,13 @@ + + - diff --git a/frameworks/FSharp/oxpecker/src/App/Common.fs b/frameworks/FSharp/oxpecker/src/App/Common.fs new file mode 100644 index 00000000000..0b62abdefee --- /dev/null +++ b/frameworks/FSharp/oxpecker/src/App/Common.fs @@ -0,0 +1,34 @@ +namespace App + +open System +open System.Collections.Generic + +[] +module Common = + + [] + [] + type JsonMessage = { + message : string + } + + [] + type Fortune = { + id: int + message: string + } + + [] + [] + type World = { + id: int + randomnumber: int + } + + [] + let ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000" + + let FortuneComparer = { + new IComparer with + member self.Compare(a,b) = String.CompareOrdinal(a.message, b.message) + } diff --git a/frameworks/FSharp/oxpecker/src/App/Db.fs b/frameworks/FSharp/oxpecker/src/App/Db.fs new file mode 100644 index 00000000000..498721b2b2e --- /dev/null +++ b/frameworks/FSharp/oxpecker/src/App/Db.fs @@ -0,0 +1,104 @@ +namespace App + +open System +open System.Data +open System.Data.Common +open System.Text +open Npgsql + + +[] +module Db = + let loadFortunes () = + let result = ResizeArray() + task { + use db = new NpgsqlConnection(ConnectionString) + use cmd = db.CreateCommand(CommandText = "SELECT id, message FROM fortune") + do! db.OpenAsync() + use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.CloseConnection) + while! rdr.ReadAsync() do + result.Add { id = rdr.GetInt32(0); message = rdr.GetString(1) } + return result + } + + let private createReadCommand (connection: DbConnection) = + let cmd = connection.CreateCommand( + CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id" + ) + let id = cmd.CreateParameter( + ParameterName = "@Id", + DbType = DbType.Int32, + Value = Random.Shared.Next(1, 10001) + ) + cmd.Parameters.Add(id) |> ignore + cmd + + let private readSingleRow (cmd: DbCommand) = + task { + use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.SingleRow) + let! _ = rdr.ReadAsync() + return { id = rdr.GetInt32(0); randomnumber = rdr.GetInt32(1) } + } + + let loadSingleRow () = + task { + use db = new NpgsqlConnection(ConnectionString) + do! db.OpenAsync() + use cmd = createReadCommand db + return! readSingleRow cmd + } + + let private readMultipleRows (count: int) (conn: NpgsqlConnection) = + let result = Array.zeroCreate count + task { + use cmd = createReadCommand conn + for i in 0..result.Length-1 do + cmd.Parameters["@Id"].Value <- Random.Shared.Next(1, 10001) + let! row = readSingleRow cmd + result[i] <- row + return result + } + + let loadMultipleRows (count: int) = + task { + use db = new NpgsqlConnection(ConnectionString) + do! db.OpenAsync() + return! readMultipleRows count db + } + + let private maxBatch = 500 + let private queries = Array.zeroCreate (maxBatch + 1) + let private batchUpdateString batchSize = + match queries[batchSize] with + | null -> + let lastIndex = batchSize - 1 + let sb = StringBuilder() + sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ") |> ignore + for i in 0..lastIndex-1 do + sb.AppendFormat("(@Id_{0}, @Rn_{0}), ", i) |> ignore + sb.AppendFormat("(@Id_{0}, @Rn_{0}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id", lastIndex) |> ignore + let result = sb.ToString() + queries[batchSize] <- result + result + | q -> + q + + let private generateParameters (results: World[]) (command: DbCommand) = + for i in 0..results.Length-1 do + let randomNumber = Random.Shared.Next(1, 10001) + let random = command.CreateParameter(ParameterName = $"@Rn_{i}", DbType = DbType.Int32, Value = randomNumber) + command.Parameters.Add(random) |> ignore + let id = command.CreateParameter(ParameterName = $"@Id_{i}", DbType = DbType.Int32, Value = results[i].id) + command.Parameters.Add(id) |> ignore + results[i] <- { results[i] with randomnumber = randomNumber } + + let doMultipleUpdates (count: int) = + task { + use conn = new NpgsqlConnection(ConnectionString) + do! conn.OpenAsync() + let! results = readMultipleRows count conn + use cmd = conn.CreateCommand(CommandText = batchUpdateString count) + do generateParameters results cmd + let! _ = cmd.ExecuteNonQueryAsync() + return results + } diff --git a/frameworks/FSharp/oxpecker/src/App/Program.fs b/frameworks/FSharp/oxpecker/src/App/Program.fs index bdb95afa593..dcfd3c53206 100644 --- a/frameworks/FSharp/oxpecker/src/App/Program.fs +++ b/frameworks/FSharp/oxpecker/src/App/Program.fs @@ -1,32 +1,8 @@ namespace App open System -open System.Collections.Generic open Oxpecker -[] -module Common = - - [] - [] - type JsonMessage = { - message : string - } - - [] - type Fortune = { - id: int - message: string - } - - [] - let ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000" - - let FortuneComparer = { - new IComparer with - member self.Compare(a,b) = String.CompareOrdinal(a.message, b.message) - } - [] module HtmlViews = open Oxpecker.ViewEngine @@ -48,7 +24,7 @@ module HtmlViews = th() { raw "message" } } - let fortunes fortunesData = + let fortunes (fortunesData: ResizeArray) = table() { fortunesTableHeader for fortune in fortunesData do @@ -60,8 +36,6 @@ module HtmlViews = [] module HttpHandlers = - open Dapper - open Npgsql open System.Text open Microsoft.AspNetCore.Http open System.Text.Json @@ -72,32 +46,24 @@ module HttpHandlers = message = "Additional fortune added at request time." } - let rec private renderFortunes (ctx: HttpContext) (dbFortunes: Fortune seq) = - let data = dbFortunes.AsList() + let rec private renderFortunes (ctx: HttpContext) (data: ResizeArray) = data.Add extra data.Sort FortuneComparer data |> HtmlViews.fortunes |> ctx.WriteHtmlView - let private fortunes : EndpointHandler = + let fortunes : EndpointHandler = fun ctx -> task { - use conn = new NpgsqlConnection(ConnectionString) - let! dbFortunes = conn.QueryAsync("SELECT id, message FROM fortune") + let! dbFortunes = loadFortunes () return! renderFortunes ctx dbFortunes } - [] - [] - type World = { - id: int - randomnumber: int - } - - let private readSingleRow (conn: NpgsqlConnection) = - conn.QueryFirstOrDefaultAsync( - "SELECT id, randomnumber FROM world WHERE id = @Id", - {| Id = Random.Shared.Next(1, 10001) |} - ) + let singleQuery : EndpointHandler = + fun ctx -> + task { + let! result = loadSingleRow() + return! ctx.WriteJsonChunked result + } let private parseQueries (ctx: HttpContext) = match ctx.TryGetRouteValue("count") with @@ -107,66 +73,19 @@ module HttpHandlers = | _, _ -> 1 | _ -> 1 - let private singleQuery : EndpointHandler = - fun ctx -> - task { - use conn = new NpgsqlConnection(ConnectionString) - let! result = readSingleRow conn - return! ctx.WriteJsonChunked result - } - - let private multipleQueries : EndpointHandler = + let multipleQueries : EndpointHandler = fun ctx -> let count = parseQueries ctx - let results = Array.zeroCreate count task { - use conn = new NpgsqlConnection(ConnectionString) - do! conn.OpenAsync() - for i in 0..results.Length-1 do - let! result = readSingleRow conn - results[i] <- result + let! results = loadMultipleRows count return! ctx.WriteJsonChunked results } - let private maxBatch = 500 - let private queries = Array.zeroCreate (maxBatch + 1) - - let private batchUpdateString batchSize = - match queries[batchSize] with - | null -> - let lastIndex = batchSize - 1 - let sb = StringBuilder() - sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES ") |> ignore - for i in 0..lastIndex-1 do - sb.AppendFormat("(@Id_{0}, @Rn_{0}), ", i) |> ignore - sb.AppendFormat("(@Id_{0}, @Rn_{0}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id", lastIndex) |> ignore - let result = sb.ToString() - queries[batchSize] <- result - result - | q -> - q - - let private generateParameters (results: World[]) = - let parameters = Dictionary() - for i in 0..results.Length-1 do - let randomNumber = Random.Shared.Next(1, 10001) - parameters[$"@Rn_{i}"] <- randomNumber - parameters[$"@Id_{i}"] <- results[i].id - results[i] <- { results[i] with randomnumber = randomNumber } - parameters - - let private multipleUpdates : EndpointHandler = + let multipleUpdates : EndpointHandler = fun ctx -> let count = parseQueries ctx - let results = Array.zeroCreate count task { - use conn = new NpgsqlConnection(ConnectionString) - do! conn.OpenAsync() - for i in 0..results.Length-1 do - let! result = readSingleRow conn - results[i] <- result - let parameters = generateParameters results - let! _ = conn.ExecuteAsync(batchUpdateString count, parameters) + let! results = doMultipleUpdates count return! ctx.WriteJsonChunked results } From 67dcfb7764f73439d83c2b9b3e658711fdad5a58 Mon Sep 17 00:00:00 2001 From: Bartosz Jarzyna <44323413+bbrtj@users.noreply.github.com> Date: Mon, 8 Jul 2024 17:28:04 +0200 Subject: [PATCH 23/62] Perl Kelp: Fix and modernize (#9115) * Perl Kelp: Fix and modernize * Perl Kelp: benchmark on multiple web servers * Perl Kelp: unfreeze framework version, a couple of fixes --- frameworks/Perl/kelp/README.md | 45 +++-- frameworks/Perl/kelp/app.ini | 3 +- frameworks/Perl/kelp/app.pl | 145 ---------------- frameworks/Perl/kelp/app.psgi | 8 + frameworks/Perl/kelp/benchmark_config.json | 168 +++++++++++++++++-- frameworks/Perl/kelp/conf/config.pl | 12 ++ frameworks/Perl/kelp/conf/test.pl | 23 +++ frameworks/Perl/kelp/config.toml | 32 ---- frameworks/Perl/kelp/kelp-mongodb.dockerfile | 27 --- frameworks/Perl/kelp/kelp.dockerfile | 40 +++-- frameworks/Perl/kelp/lib/KelpBench.pm | 130 ++++++++++++++ frameworks/Perl/kelp/lib/KelpBench/DBI.pm | 47 ++++++ frameworks/Perl/kelp/lib/KelpBench/Mongo.pm | 43 +++++ frameworks/Perl/kelp/run.pl | 78 +++++++++ frameworks/Perl/kelp/t/main.t | 111 ++++++++---- frameworks/Perl/kelp/views/fortunes.tt | 22 +++ 16 files changed, 659 insertions(+), 275 deletions(-) delete mode 100755 frameworks/Perl/kelp/app.pl create mode 100755 frameworks/Perl/kelp/app.psgi create mode 100644 frameworks/Perl/kelp/conf/config.pl create mode 100644 frameworks/Perl/kelp/conf/test.pl delete mode 100644 frameworks/Perl/kelp/config.toml delete mode 100644 frameworks/Perl/kelp/kelp-mongodb.dockerfile create mode 100644 frameworks/Perl/kelp/lib/KelpBench.pm create mode 100644 frameworks/Perl/kelp/lib/KelpBench/DBI.pm create mode 100644 frameworks/Perl/kelp/lib/KelpBench/Mongo.pm create mode 100755 frameworks/Perl/kelp/run.pl create mode 100644 frameworks/Perl/kelp/views/fortunes.tt diff --git a/frameworks/Perl/kelp/README.md b/frameworks/Perl/kelp/README.md index f66a3470d67..8be16d73c02 100644 --- a/frameworks/Perl/kelp/README.md +++ b/frameworks/Perl/kelp/README.md @@ -1,18 +1,17 @@ # Setup -* Perl 5.10+ -* MySQL 5.5 -* MongoDB -* Wrk 2.0 +* Perl 5.36+ +* MariaDB or MongoDB # Requirements * Kelp (install from CPAN) -* Kelp::Module::JSON::XS (install from CPAN) * Kelp::Module::Template::Toolkit (install from CPAN) -* DBD::mysql (install from CPAN) +* DBI + DBD::mysql or MongoDB (install from CPAN) +* Gazelle (install from CPAN) * Starman (install from CPAN) -* MongoDB (install from CPAN) +* Starlet (install from CPAN) +* Twiggy::Prefork (install from CPAN) * nginx (if you want to front with nginx, nginx.conf provided) # Deployment @@ -24,16 +23,38 @@ ./uwsgi --plugins psgi --init app.ini -## Plack + Starman +## Plack + plack handler -1. Deploy via plackup +Recommended handler is `Gazelle`. - plackup -E deployment -s Starman --workers=25 -l /tmp/frameworks-benchmark.sock -a ./app.pl +1. Deploy via `start_server`, if you want to front it with nginx. -2. If you want to front it with nginx, otherwise + start_server --path /tmp/perl-kelp.sock --backlog 16384 -- plackup -E production -s Gazelle --max-workers=25 --max-reqs-per-child=10000 -a ./app.psgi - plackup -E deployment -s Starman --port=8080 --workers=25 -a ./app.pl +2. Otherwise + + plackup -E deployment -s Gazelle --port=8080 --max-workers=25 -a ./app.psgi + +# Code information + +`lib/KelpBench.pm` contains all action-handling and helper code. It is a full +Kelp app with `Template::Toolkit` module and standard Kelp configuration files. +While it could've been coded as a one-file Kelp app, full app style gives us +more control on the behavior of the app. It lazy-loads `DBI.pm` or `Mongo.pm` +from `lib/KelpBench/` directory based on environmental variable `MONGO`, so it +only needs one database driver at a time. + +The app is written in a relaxed style, not trying very hard to achieve the best +possible result. It very much resembles production code. For example, a proper +templating engine is used to produce the HTML document instead of inline HTML +(which is obviously much faster). + +App can be tested using mock database by running `prove -l`. In this case, it +only requires `Kelp` and `Kelp::Module::Template::Toolkit` from CPAN to be +installed. # Expert contact +@bbrtj (contact@bbrtj.eu) @naturalist (minimal@cpan.org) + diff --git a/frameworks/Perl/kelp/app.ini b/frameworks/Perl/kelp/app.ini index 7a53ad301ae..ebeb49abedf 100644 --- a/frameworks/Perl/kelp/app.ini +++ b/frameworks/Perl/kelp/app.ini @@ -1,4 +1,5 @@ [uwsgi] http-socket = :8080 -psgi = app.pl +psgi = app.psgi disable-logging = True + diff --git a/frameworks/Perl/kelp/app.pl b/frameworks/Perl/kelp/app.pl deleted file mode 100755 index 8db36540926..00000000000 --- a/frameworks/Perl/kelp/app.pl +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env perl - -use Kelp::Less; -use HTML::Escape 'escape_html'; -use MongoDB; -use DBI; -use utf8; - -module 'JSON::XS'; - -my $mongo; -my $mdb; -my $world; -my $fortune; -my @sth; -my $dbh; - -if ($ENV{MONGO}) { - $mongo = MongoDB::MongoClient->new( host => 'tfb-database', port => 27017 ); - $mdb = $mongo->get_database('hello_world'); - $world = $mdb->get_collection('world'); - $fortune = $mdb->get_collection('fortune'); -} else { - $dbh = DBI->connect( - "dbi:mysql:database=hello_world;host=tfb-database;port=3306", - 'benchmarkdbuser', - 'benchmarkdbpass', - { RaiseError => 0, PrintError => 0, mysql_enable_utf8 => 1 } - ); - @sth = map { $dbh->prepare($_) } ( - "SELECT * FROM World WHERE id = ?", - "SELECT * FROM Fortune", - "UPDATE World SET randomNumber = ? WHERE id = ?", - ); -} - -get '/json' => sub { - { message => 'Hello, World!' }; -}; - -get '/db/?db' => sub { - my ( $self, $db ) = @_; - my $id = int rand 10000 + 1; - my $row; - if ( $db eq 'mongo' ) { - $row = $world->find_one( { _id => $id } ); - } - else { - $sth[0]->execute($id); - $row = $sth[0]->fetchrow_hashref; - } - return { id => $id, randomNumber => $row->{randomNumber} }; -}; - -get '/queries/?db' => sub { - my ( $self, $db ) = @_; - query( $db // 'mongo', $self->param('queries') ); -}; - -get '/fortunes/?db' => sub { - my ( $self, $db ) = @_; - $db //= 'mongo'; - my @objects; - if ( $db eq 'mongo' ) { - my $cursor = $fortune->query( {} ); - @objects = $cursor->all; - } - else { - $sth[1]->execute(); - @objects = @{ $sth[1]->fetchall_arrayref( {} ) }; - } - push @objects, { id => 0, message => "Additional fortune added at request time." }; - fortunes( \@objects ); -}; - -get '/update/?db' => sub { - my ( $self, $db ) = @_; - $db //= 'mongo'; - - my $arr = query( $db, $self->param('queries') ); - $arr = [$arr] unless ref($arr) eq 'ARRAY'; - for my $row (@$arr) { - $row->{randomNumber} = int( rand(10_000) ) + 1; - if ( $db eq 'mongo' ) { - $world->update( { _id => $row->{id} }, - { randomNumber => $row->{randomNumber} } ); - } - else { - $row->{randomNumber} = int( rand(10_000) ) + 1; - $sth[2]->execute( $row->{randomNumber}, $row->{id} ); - } - } - - return $arr; -}; - -get '/plaintext' => sub { - shift->res->text->render('Hello, World!'); -}; - -run; - -sub query { - my ( $db, $count ) = @_; - $count //= 1; - $count = 1 if ( $count !~ /^\d+$/ || $count < 1 ); - $count = 500 if $count > 500; - my @response; - for ( 1 .. $count ) { - my $id = int rand 10000 + 1; - my $row; - if ( $db eq 'mongo' ) { - $row = $world->find_one( { _id => $id } ); - } - else { - $sth[0]->execute($id); - $row = $sth[0]->fetchrow_hashref; - } - if ($row) { - push @response, - { id => $id, randomNumber => $row->{randomNumber} }; - } - } - return \@response; -} - -sub fortunes { - my ($objects) = @_; - my $res = q[Fortunes]; - $res .= q[]; - - for my $item ( sort { $a->{message} cmp $b->{message} } @$objects ) { - my $id = $item->{id}; - my $message = escape_html( $item->{message} ); - - # HTML::Escape encodes apostrophe as ' because IE8 does not - # support '. We forse an ' here in order to pass the - # test - $message =~ s/'/&apos/g; - $res .= ""; - } - - $res .= q[
idmessage
$id$message
]; - return $res; -} diff --git a/frameworks/Perl/kelp/app.psgi b/frameworks/Perl/kelp/app.psgi new file mode 100755 index 00000000000..5a8182549bd --- /dev/null +++ b/frameworks/Perl/kelp/app.psgi @@ -0,0 +1,8 @@ +#!/usr/bin/env perl + +use Path::Tiny qw(path); +use lib path(__FILE__)->parent->child('lib'); +use KelpBench; + +KelpBench->new->run; + diff --git a/frameworks/Perl/kelp/benchmark_config.json b/frameworks/Perl/kelp/benchmark_config.json index 036f68fd31f..1cd06f51ad0 100644 --- a/frameworks/Perl/kelp/benchmark_config.json +++ b/frameworks/Perl/kelp/benchmark_config.json @@ -1,11 +1,61 @@ { "framework": "kelp", "tests": [{ - "default": { - "db_url": "/db/mysql", - "query_url": "/queries/mysql?queries=", - "fortune_url": "/fortunes/mysql", + "gazelle-mysql": { + "dockerfile": "kelp.dockerfile", "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MySQL", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Gazelle", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] + }, + "gazelle-mongodb": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MongoDB", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Gazelle", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] + }, + + "starman-mysql": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Fullstack", @@ -17,16 +67,18 @@ "webserver": "Starman", "os": "Linux", "database_os": "Linux", - "display_name": "kelp", "notes": "", "versus": "", - "tags": ["broken"] + "tags": [] }, - "mongodb": { - "db_url": "/db/mongo", - "query_url": "/queries/mongo?queries=", - "fortune_url": "/fortunes/mongo", + "starman-mongodb": { + "dockerfile": "kelp.dockerfile", "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Fullstack", @@ -38,10 +90,102 @@ "webserver": "Starman", "os": "Linux", "database_os": "Linux", - "display_name": "kelp", "notes": "", "versus": "", - "tags": ["broken"] + "tags": [] + }, + + "starlet-mysql": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MySQL", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Starlet", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] + }, + "starlet-mongodb": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MongoDB", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Starlet", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] + }, + + "twiggy-mysql": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MySQL", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Twiggy", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] + }, + "twiggy-mongodb": { + "dockerfile": "kelp.dockerfile", + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MongoDB", + "framework": "kelp", + "language": "Perl", + "orm": "Raw", + "platform": "Plack", + "webserver": "Twiggy", + "os": "Linux", + "database_os": "Linux", + "notes": "", + "versus": "", + "tags": [] } }] } + diff --git a/frameworks/Perl/kelp/conf/config.pl b/frameworks/Perl/kelp/conf/config.pl new file mode 100644 index 00000000000..ce7f3527f59 --- /dev/null +++ b/frameworks/Perl/kelp/conf/config.pl @@ -0,0 +1,12 @@ +{ + modules => [qw(JSON Template::Toolkit)], + modules_init => { + 'Template::Toolkit' => { + STRICT => 1, + OUTLINE_TAG => qr{\V*%%}, # https://github.com/abw/Template2/issues/320 + ENCODING => 'utf8', + INCLUDE_PATH => 'views', + }, + }, +} + diff --git a/frameworks/Perl/kelp/conf/test.pl b/frameworks/Perl/kelp/conf/test.pl new file mode 100644 index 00000000000..f480597ed9b --- /dev/null +++ b/frameworks/Perl/kelp/conf/test.pl @@ -0,0 +1,23 @@ +{ + '+modules' => [qw(Logger)], + + modules_init => { + Logger => { + outputs => [ + [ + 'Screen', + name => 'logs', + min_level => 'debug', + stderr => 1, + newline => 1, + utf8 => 1, + ], + ], + }, + + 'Template::Toolkit' => { + DEBUG => 1, + }, + }, +} + diff --git a/frameworks/Perl/kelp/config.toml b/frameworks/Perl/kelp/config.toml deleted file mode 100644 index 7e997486fb2..00000000000 --- a/frameworks/Perl/kelp/config.toml +++ /dev/null @@ -1,32 +0,0 @@ -[framework] -name = "kelp" - -[main] -urls.plaintext = "/plaintext" -urls.db = "/db/mysql" -urls.query = "/queries/mysql?queries=" -urls.fortune = "/fortunes/mysql" -approach = "Realistic" -classification = "Fullstack" -database = "MySQL" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Plack" -webserver = "Starman" -versus = "" - -[mongodb] -urls.plaintext = "/plaintext" -urls.db = "/db/mongo" -urls.query = "/queries/mongo?queries=" -urls.fortune = "/fortunes/mongo" -approach = "Realistic" -classification = "Fullstack" -database = "MongoDB" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "Plack" -webserver = "Starman" -versus = "" diff --git a/frameworks/Perl/kelp/kelp-mongodb.dockerfile b/frameworks/Perl/kelp/kelp-mongodb.dockerfile deleted file mode 100644 index 783c7e4d263..00000000000 --- a/frameworks/Perl/kelp/kelp-mongodb.dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM perl:5.26 - -RUN apt-get update -yqq && apt-get install -yqq nginx - -WORKDIR /kelp - -RUN cpanm --notest --no-man-page \ - JSON JSON::XS IO::Socket::IP IO::Socket::SSL \ - Kelp@0.9071 \ - DBI@1.636 \ - DBD::mysql@4.033 \ - MongoDB@1.8.1 \ - Kelp::Module::JSON::XS@0.502 \ - HTML::Escape@1.10 \ - HTTP::Parser::XS@0.17 \ - Starman@0.4014 - -ADD ./app.ini /kelp/ -ADD ./app.pl /kelp/ -ADD ./nginx.conf /kelp/ - -ENV MONGO=1 - -EXPOSE 8080 - -CMD nginx -c /kelp/nginx.conf && \ - plackup -E production -s Starman --workers=$(nproc) -l /tmp/perl-kelp.sock -a ./app.pl diff --git a/frameworks/Perl/kelp/kelp.dockerfile b/frameworks/Perl/kelp/kelp.dockerfile index 7bfd6f33521..b8bd3453317 100644 --- a/frameworks/Perl/kelp/kelp.dockerfile +++ b/frameworks/Perl/kelp/kelp.dockerfile @@ -1,25 +1,33 @@ -FROM perl:5.26 +FROM perl:5.40 + +ARG TFB_TEST_NAME +ARG TFB_TEST_DATABASE RUN apt-get update -yqq && apt-get install -yqq nginx WORKDIR /kelp RUN cpanm --notest --no-man-page \ - JSON JSON::XS IO::Socket::IP IO::Socket::SSL \ - Kelp@0.9071 \ - DBI@1.636 \ - DBD::mysql@4.033 \ - MongoDB@1.8.1 \ - Kelp::Module::JSON::XS@0.502 \ - HTML::Escape@1.10 \ - HTTP::Parser::XS@0.17 \ - Starman@0.4014 - -ADD ./app.ini /kelp/ -ADD ./app.pl /kelp/ -ADD ./nginx.conf /kelp/ + Kelp::Module::Template::Toolkit@0.301 \ + Kelp \ + DBI@1.643 \ + DBD::MariaDB@1.23 \ + MongoDB@2.2.2 \ + Cpanel::JSON::XS@4.38 \ + Gazelle@0.49 \ + Starman@0.4017 \ + Starlet@0.31 \ + Twiggy::Prefork@0.08 \ + Net::Server::SS::PreFork@0.05 + +ADD ./ /kelp/ + +ENV TEST_NAME=$TFB_TEST_NAME +ENV DATABASE=$TFB_TEST_DATABASE +ENV MAX_REQS=100000 +ENV SOCKET_FILE=/tmp/perl-kelp.sock EXPOSE 8080 -CMD nginx -c /kelp/nginx.conf && \ - plackup -E production -s Starman --workers=$(nproc) -l /tmp/perl-kelp.sock -a ./app.pl +CMD nginx -c /kelp/nginx.conf && ./run.pl + diff --git a/frameworks/Perl/kelp/lib/KelpBench.pm b/frameworks/Perl/kelp/lib/KelpBench.pm new file mode 100644 index 00000000000..d20a72a31ed --- /dev/null +++ b/frameworks/Perl/kelp/lib/KelpBench.pm @@ -0,0 +1,130 @@ +package KelpBench; + +use v5.36; +use Kelp::Base 'Kelp'; + +## Attributes + +attr database => sub { + if (lc $ENV{DATABASE} eq 'mongodb') { + require KelpBench::Mongo; + return KelpBench::Mongo->new; + } + elsif (lc $ENV{DATABASE} eq 'mysql') { + require KelpBench::DBI; + return KelpBench::DBI->new; + } + else { + die "unknown database chosen: $ENV{DATABASE}"; + } +}; + +## Utilities + +sub validate_number ($self, $num, $min, $max) +{ + return $min unless length($num // '') && $num !~ /\D/; + return $min if $num < $min; + return $max if $num > $max; + return $num; +} + +sub random_number ($self, $max = 10_000) +{ + return int(rand($max) + 1); +} + +sub random_id ($self) +{ + # in case random ids were not the same as random numbers + return $self->random_number(10_000); +} + +sub get_random_entries ($self, $count) +{ + $count = $self->validate_number($count, 1, 500); + + my @result; + for (1 .. $count) { + my $id = $self->random_id; + my $row = $self->database->random_number($id); + next unless $row; + + push @result, { + id => $id, + randomNumber => $row->{randomNumber} + }; + } + + return \@result; +} + +## Framework code + +sub before_dispatch {} # skip trying to log access +sub before_finalize {} # skip adding X-Framework + +sub build ($self) +{ + $self->add_route([GET => '/plaintext'] => 'action_plaintext'); + $self->add_route([GET => '/json'] => 'action_json'); + $self->add_route([GET => '/db'] => 'action_db'); + $self->add_route([GET => '/queries'] => 'action_queries'); + $self->add_route([GET => '/fortunes'] => 'action_fortunes'); + $self->add_route([GET => '/updates'] => 'action_updates'); +} + +## Registered route handlers +## Names prefixed with _action, because we did not separate a controller +## (Controllers would slow this down a bit due to reblessing of app object) + +sub action_plaintext ($self) +{ + $self->res->text; + return 'Hello, World!'; +} + +sub action_json ($self) +{ + return { message => 'Hello, World!' }; +} + +sub action_db ($self) +{ + my $id = $self->random_id; + my $row = $self->database->random_number($id); + + return { id => $id, randomNumber => $row->{randomNumber} }; +} + +sub action_queries ($self) +{ + return $self->get_random_entries($self->req->query_param('queries')); +} + +sub action_fortunes ($self) { + my $objects = $self->database->fortune; + + push $objects->@*, { + id => 0, + message => "Additional fortune added at request time." + }; + + $objects->@* = sort { $a->{message} cmp $b->{message} } $objects->@*; + return $self->template('fortunes', { rows => $objects }); +} + +sub action_updates ($self) +{ + my $arr = $self->get_random_entries($self->req->query_param('queries')); + + foreach my $row ($arr->@*) { + $row->{randomNumber} = $self->random_number; + $self->database->update($row->@{qw(id randomNumber)}); + } + + return $arr; +}; + +1; + diff --git a/frameworks/Perl/kelp/lib/KelpBench/DBI.pm b/frameworks/Perl/kelp/lib/KelpBench/DBI.pm new file mode 100644 index 00000000000..15440bff07e --- /dev/null +++ b/frameworks/Perl/kelp/lib/KelpBench/DBI.pm @@ -0,0 +1,47 @@ +package KelpBench::DBI; + +use v5.36; +use Kelp::Base 'Kelp'; +use DBI; + +attr dbh => sub { + DBI->connect( + "dbi:MariaDB:database=hello_world;host=tfb-database;port=3306", + 'benchmarkdbuser', + 'benchmarkdbpass', + { RaiseError => 1, PrintError => 0 } + ); +}; + +attr _world => sub ($self) { + $self->dbh->prepare("SELECT * FROM World WHERE id = ?"); +}; + +attr _fortune => sub ($self) { + $self->dbh->prepare("SELECT * FROM Fortune"); +}; + +attr _update => sub ($self) { + $self->dbh->prepare("UPDATE World SET randomNumber = ? WHERE id = ?"); +}; + +sub random_number ($self, $id) +{ + $self->_world->execute($id); + return $self->_world->fetchrow_hashref; +} + +sub fortune ($self) +{ + $self->_fortune->execute(); + return $self->_fortune->fetchall_arrayref({}); +} + +sub update ($self, $id, $random_number) +{ + $self->_update->execute($random_number, $id); + return; +} + +1; + diff --git a/frameworks/Perl/kelp/lib/KelpBench/Mongo.pm b/frameworks/Perl/kelp/lib/KelpBench/Mongo.pm new file mode 100644 index 00000000000..3af50e54c12 --- /dev/null +++ b/frameworks/Perl/kelp/lib/KelpBench/Mongo.pm @@ -0,0 +1,43 @@ +package KelpBench::Mongo; + +use v5.36; +use Kelp::Base 'Kelp'; +use MongoDB; + +attr dbh => sub { + MongoDB::MongoClient->new( + host => 'tfb-database', + port => 27017 + )->get_database('hello_world'); +}; + +attr _world => sub ($self) { + $self->dbh->get_collection('world'); +}; + +attr _fortune => sub ($self) { + $self->dbh->get_collection('fortune'); +}; + +sub random_number ($self, $id) +{ + return $self->_world->find_one({ _id => $id }); +} + +sub fortune ($self) +{ + return [$self->_fortune->find->all]; +} + +sub update ($self, $id, $random_number) +{ + $self->_world->update_one( + { _id => $id }, + { '$set' => { randomNumber => $random_number } }, + ); + + return; +} + +1; + diff --git a/frameworks/Perl/kelp/run.pl b/frameworks/Perl/kelp/run.pl new file mode 100755 index 00000000000..b8436498f64 --- /dev/null +++ b/frameworks/Perl/kelp/run.pl @@ -0,0 +1,78 @@ +#!/usr/bin/env perl + +use v5.36; +use Data::Dumper; + +my $max_reqs = $ENV{MAX_REQS}; +my $test_name = $ENV{TEST_NAME}; +my $socket_file = $ENV{SOCKET_FILE}; +my $app_runner = 'app.psgi'; + +my $max_workers = `nproc`; +chomp $max_workers; + +my %runner_map = ( + gazelle => [ + 'start_server', + '--path' => $socket_file, + '--backlog' => 16384, + '--', + 'plackup', + '-E' => 'production', + '-s' => 'Gazelle', + '--max-workers' => $max_workers, + '--max-reqs-per-child' => $max_reqs, + '-a' => $app_runner, + ], + starman => [ + 'start_server', + '--backlog' => 16384, + '--', + 'plackup', + '-E' => 'production', + '-s' => 'Starman', + '-l' => $socket_file, + '--workers' => $max_workers, + '--max-requests' => $max_reqs, + '-a' => $app_runner, + ], + starlet => [ + 'start_server', + '--path' => $socket_file, + '--backlog' => 16384, + '--', + 'plackup', + '-E' => 'production', + '-s' => 'Starlet', + '--max-workers' => $max_workers, + '--max-reqs-per-child' => $max_reqs, + '-a' => $app_runner, + ], + # NOTE: twiggy does not play well with Server::Starter + # NOTE: twiggy couldn't pass update tests, so I disabled them + twiggy => [ + 'plackup', + '-E' => 'production', + '-s' => 'Twiggy::Prefork', + '-l' => $socket_file, + '--backlog' => 16384, + '--max-workers' => $max_workers, + '--max-reqs-per-child' => $max_reqs, + '-a' => $app_runner, + ], +); + +die "invalid test name $test_name" + unless $test_name =~ m{^kelp-(\w+)-(\w+)$}; + +die 'database mismatch' + unless $2 eq $ENV{DATABASE}; + +my $command = $runner_map{$1}; +die "invalid server $1" + unless $command; + +say 'Running command: ' . Dumper($command); + +exec @$command; + diff --git a/frameworks/Perl/kelp/t/main.t b/frameworks/Perl/kelp/t/main.t index 8d816c95324..a682ca112cf 100644 --- a/frameworks/Perl/kelp/t/main.t +++ b/frameworks/Perl/kelp/t/main.t @@ -1,56 +1,107 @@ -use strict; -use warnings; +use v5.36; use utf8; use Kelp::Test; use Test::More; use Test::Deep; use HTTP::Request::Common; +use KelpBench; -my $t = Kelp::Test->new( psgi => 'app.pl'); -my $world = { randomNumber => re(qr{^\d+$}), id => re(qr{^\d+$}) }; +# use mock to avoid the need for DB modules and actual running DB +# (however, we do not test for DB code correctness this way) +package DBMock { + use v5.36; + use utf8; -subtest 'json' => sub { - $t->request( GET '/json' )->json_cmp( { message => 'Hello, World!' } ); + use Kelp::Base; + + sub random_number ($self, $id) + { + return { + id => $id, + randomNumber => int(rand(10_000) + 1), + }; + } + + sub fortune ($self) + { + return [ + { + id => 1, + message => 'フレームワークのベンチマーク', + }, + { + id => 2, + message => '', + }, + { + id => 3, + message => '&&/\\+?', + }, + ]; + } + + sub update ($self, $id, $random_number) + { + return; + } }; +my $app = KelpBench->new(mode => 'test', database => DBMock->new); +my $t = Kelp::Test->new(app => $app); +my $world = { randomNumber => re(qr{^\d+$}), id => re(qr{^\d+$}) }; + subtest plaintext => sub { - $t->request( GET '/plaintext' ) - ->content_type_is('text/plain') - ->content_is('Hello, World!'); + my $uri = '/plaintext'; + + $t->request(GET $uri) + ->content_type_is('text/plain') + ->content_is('Hello, World!'); +}; + +subtest 'json' => sub { + my $uri = '/json'; + + $t->request(GET $uri) + ->json_cmp({ message => 'Hello, World!' }); }; subtest db => sub { - for my $uri (qw{/db /db/mongo}) { - $t->request( GET $uri )->json_cmp($world); - } + my $uri = '/db'; + + $t->request(GET $uri) + ->json_cmp($world); }; subtest queries => sub { - for my $uri (qw{/queries /queries/mongo}) { - $t->request( GET $uri )->json_cmp($world); - $t->request( GET "$uri?queries=3" ) - ->json_cmp( [ $world, $world, $world ] ); - $t->request( GET "$uri?queries=0" )->json_cmp($world); - } + my $uri = '/queries'; + + $t->request(GET $uri) + ->json_cmp([$world]); + $t->request(GET "$uri?queries=3") + ->json_cmp([$world, $world, $world]); + $t->request(GET "$uri?queries=0") + ->json_cmp([$world]); }; subtest update => sub { - for my $uri (qw{/update /update/mongo}) { - $t->request( GET $uri )->json_cmp([$world]); - $t->request( GET "$uri?queries=3" ) - ->json_cmp( [ $world, $world, $world ] ); - } + my $uri = '/updates'; + + $t->request(GET $uri) + ->json_cmp([$world]); + $t->request(GET "$uri?queries=3") + ->json_cmp([ $world, $world, $world ]); }; subtest fortunes => sub { - for my $uri (qw{/fortunes /fortunes/mongo}) { - $t->request( GET $uri ) - ->content_type_is('text/html') - ->content_like(qr{<script>}) - ->content_like(qr{フレームワークのベンチマーク}) - ->content_like(qr{Additional fortune added at request time.}); - } + my $uri = '/fortunes'; + + $t->request(GET $uri) + ->content_type_is('text/html') + ->content_like(qr{<script>}) + ->content_like(qr{フレームワークのベンチマーク}) + ->content_like(qr{Additional fortune added at request time.}); }; done_testing; + diff --git a/frameworks/Perl/kelp/views/fortunes.tt b/frameworks/Perl/kelp/views/fortunes.tt new file mode 100644 index 00000000000..9667485892f --- /dev/null +++ b/frameworks/Perl/kelp/views/fortunes.tt @@ -0,0 +1,22 @@ + + + + Fortunes + + + + + + + + + %% FOREACH row IN rows + + + + + %% END +
idmessage
[% row.id %][% row.message | html %]
+ + + From 33500e87c5e5892a027203d90176e4906816d3c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=91=E5=B0=8F=E9=A9=AC?= <1417262058@qq.com> Date: Mon, 8 Jul 2024 23:28:23 +0800 Subject: [PATCH 24/62] Updating performance issues in the HServer framework. (#9119) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * hserver framework submit * hserver framework submit * lowercase fix * Required response header missing: Date fix * Date format fix * update hserver version * update hserver threadPool * update hserver * update hserver * update hserver query * update hserver query * Update README.md * update hserver query * update hserver query * update hserver query * update hserver query * update hserver query * update hserver query * Optimal configuration of hserver framework * Optimal configuration of hserver framework * Optimal configuration of hserver framework * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration * Update pom.xml Upgrade dependencies, optimize performance. * Upgrade hserver Framework version and optimize configuration * Upgrade hserver Framework version and optimize configuration and Optimize log printing * Update pom.xml * Update StartApp.java --------- Co-authored-by: 黑小马 --- frameworks/Java/hserver/pom.xml | 2 +- .../Java/hserver/src/main/java/com/test/hserver/StartApp.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/frameworks/Java/hserver/pom.xml b/frameworks/Java/hserver/pom.xml index 4e304e8caf9..b841cbd60ab 100644 --- a/frameworks/Java/hserver/pom.xml +++ b/frameworks/Java/hserver/pom.xml @@ -11,7 +11,7 @@ hserver-parent cn.hserver - 3.4.M2 + 3.5.M2 UTF-8 diff --git a/frameworks/Java/hserver/src/main/java/com/test/hserver/StartApp.java b/frameworks/Java/hserver/src/main/java/com/test/hserver/StartApp.java index 87c5642d0b8..b4e215081da 100644 --- a/frameworks/Java/hserver/src/main/java/com/test/hserver/StartApp.java +++ b/frameworks/Java/hserver/src/main/java/com/test/hserver/StartApp.java @@ -13,8 +13,6 @@ public class StartApp { public static void main(String[] args) { - ConstConfig.bossPool = Runtime.getRuntime().availableProcessors()/2; - ConstConfig.workerPool = Runtime.getRuntime().availableProcessors(); HServerApplication.run(StartApp.class, 8888, args); } } From 9dffd6a7761897deb17ffb676e3500e4ac2ae4a3 Mon Sep 17 00:00:00 2001 From: Julien Viet Date: Mon, 8 Jul 2024 17:28:39 +0200 Subject: [PATCH 25/62] [java/vertx] Vert.x 4.5.8 bump + bunch of improvements (#9142) * Other contenders have clearly demonstrated that update benchmark performs better using a prepared statement with a aggregation of tuples instead of a postgres batch with a list of tuple. This change shamelessly borrows the SQL statement uwebsockets (thank you uwebsockets) with a small tweaks for the datatype. In other words UPDATE world SET randomNumber = update_data.randomNumber FROM (VALUES ($1::int,$2::int),...) AS update_data (id, randomNumber) WHERE world.id = update_data.id is superior (in this context) to a batch of UPDATE world SET randomnumber=$1 WHERE id=$2 * Use a single event-loop per CPU instead of the double. * Trim whitespace in rocker templates, shamelessly borrowed from Quarkus/Vertx benchmark. * Use a collecting query for fortunes that maps a row to a fortune instance which allocates a single row instance. This avoids allocating intermedary rows object when we map them to Fortune instances. Xerox tip: TFB Contenders using vertx-pg-client should copy this change to save some cycles. * Allocate a JsonArray of the right size for the query benchmark, avoid un-necessary string conversion in the generated JSON. * Avoid using Jackson databind that is actually not needed * Split reading/writing to the world table in two separate connections for the update benchmark, the hypothesis is that for the update benchmark first read then write to the World table, even though the write depends on the read, each change has a queue (the pipelined statements) and using two connections adds the operation to a queue with a smaller latency. This seems to give better results in my benchmark, let's see how this behaves out there. Xerox tip: TFB Contenders using vertx-pg-client should copy this change to save some cycles. * Bump Vert.x to 4.5.8 and its deps. --- frameworks/Java/vertx/pom.xml | 15 +- .../Java/vertx/src/main/java/vertx/App.java | 167 +++++++++++------- .../main/java/vertx/model/CachedWorld.java | 7 +- .../src/main/java/vertx/model/World.java | 7 +- .../src/main/java/vertx/model/WorldCache.java | 7 +- .../vertx/FortunesTemplate.rocker.html | 20 +-- 6 files changed, 132 insertions(+), 91 deletions(-) diff --git a/frameworks/Java/vertx/pom.xml b/frameworks/Java/vertx/pom.xml index 12ef914a5c5..cdb3aa09f6a 100644 --- a/frameworks/Java/vertx/pom.xml +++ b/frameworks/Java/vertx/pom.xml @@ -10,10 +10,10 @@ 17 vertx.App - 4.5.3 - 2.15.0 - 4.1.92.Final - 0.0.21.Final + 4.5.8 + 2.16.1 + 4.1.110.Final + 0.0.25.Final @@ -32,11 +32,6 @@ jackson-core ${jackson.version}
- - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - io.netty netty-transport-native-kqueue @@ -91,7 +86,7 @@ 17 ${basedir}/src/main/templates ${basedir}/target/generated-sources/rocker - false + true true true true diff --git a/frameworks/Java/vertx/src/main/java/vertx/App.java b/frameworks/Java/vertx/src/main/java/vertx/App.java index 6d225d77d6c..5e81292d8ed 100755 --- a/frameworks/Java/vertx/src/main/java/vertx/App.java +++ b/frameworks/Java/vertx/src/main/java/vertx/App.java @@ -12,17 +12,11 @@ import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; -import io.vertx.core.json.Json; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; -import io.vertx.sqlclient.PreparedQuery; -import io.vertx.sqlclient.PreparedStatement; -import io.vertx.sqlclient.Row; -import io.vertx.sqlclient.RowIterator; -import io.vertx.sqlclient.RowSet; -import io.vertx.sqlclient.Tuple; +import io.vertx.sqlclient.*; import io.vertx.sqlclient.impl.SqlClientInternal; import vertx.model.CachedWorld; import vertx.model.Fortune; @@ -41,7 +35,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @@ -102,7 +95,8 @@ static int getQueries(HttpServerRequest request) { private static final String SELECT_WORLDS = "SELECT id, randomnumber from WORLD"; private HttpServer server; - private SqlClientInternal client; + private SqlClientInternal client1; + private SqlClientInternal client2; private CharSequence dateString; private CharSequence[] plaintextHeaders; @@ -110,8 +104,10 @@ static int getQueries(HttpServerRequest request) { private Throwable databaseErr; private PreparedQuery> SELECT_WORLD_QUERY; - private PreparedQuery> SELECT_FORTUNE_QUERY; + private PreparedQuery>> SELECT_FORTUNE_QUERY; private PreparedQuery> UPDATE_WORLD_QUERY; + @SuppressWarnings("unchecked") + private PreparedQuery>[] AGGREGATED_UPDATE_WORLD_QUERY = new PreparedQuery[128]; private WorldCache WORLD_CACHE; public static CharSequence createDateHeader() { @@ -139,28 +135,67 @@ public void start(Promise startPromise) throws Exception { options.setPassword(config.getString("password", "benchmarkdbpass")); options.setCachePreparedStatements(true); options.setPipeliningLimit(100_000); // Large pipelining means less flushing and we use a single connection anyway - PgConnection.connect(vertx, options) + Future clientsInit = initClients(options); + clientsInit + .transform(ar -> { + databaseErr = ar.cause(); + return server.listen(port); + }) + .mapEmpty() + .onComplete(startPromise); + } + + private Future initClients(PgConnectOptions options) { + Future cf1 = PgConnection.connect(vertx, options) .flatMap(conn -> { - client = (SqlClientInternal) conn; + client1 = (SqlClientInternal) conn; + List> list = new ArrayList<>(); Future f1 = conn.prepare(SELECT_WORLD) .andThen(onSuccess(ps -> SELECT_WORLD_QUERY = ps.query())); + list.add(f1); Future f2 = conn.prepare(SELECT_FORTUNE) - .andThen(onSuccess(ps -> SELECT_FORTUNE_QUERY = ps.query())); - Future f3 = conn.prepare(UPDATE_WORLD) - .andThen(onSuccess(ps -> UPDATE_WORLD_QUERY = ps.query())); - Future f4 = conn.preparedQuery(SELECT_WORLDS) + .andThen(onSuccess(ps -> { + SELECT_FORTUNE_QUERY = ps.query(). + collecting(Collectors.mapping(row -> new Fortune(row.getInteger(0), row.getString(1)), Collectors.toList())); + })); + list.add(f2); + Future f3 = conn.preparedQuery(SELECT_WORLDS) .collecting(Collectors.mapping(row -> new CachedWorld(row.getInteger(0), row.getInteger(1)), Collectors.toList())) .execute() .map(worlds -> new WorldCache(worlds.value())) .andThen(onSuccess(wc -> WORLD_CACHE = wc)); - return CompositeFuture.join(f1, f2, f3, f4); - }) - .transform(ar -> { - databaseErr = ar.cause(); - return server.listen(port); - }) - .mapEmpty() - .onComplete(startPromise); + list.add(f3); + return Future.join(list); + }); + Future cf2 = PgConnection.connect(vertx, options) + .flatMap(conn -> { + client2 = (SqlClientInternal) conn; + List> list = new ArrayList<>(); + Future f1 = conn.prepare(UPDATE_WORLD) + .andThen(onSuccess(ps -> UPDATE_WORLD_QUERY = ps.query())); + list.add(f1); + for (int i = 0; i < AGGREGATED_UPDATE_WORLD_QUERY.length; i++) { + int idx = i; + Future fut = conn + .prepare(buildAggregatedUpdateQuery(1 + idx)) + .andThen(onSuccess(ps -> AGGREGATED_UPDATE_WORLD_QUERY[idx] = ps.query())); + list.add(fut); + } + return Future.join(list); + }); + return Future.join(cf1, cf2); + } + + private static String buildAggregatedUpdateQuery(int len) { + StringBuilder sb = new StringBuilder(); + sb.append("UPDATE world SET randomNumber = update_data.randomNumber FROM (VALUES"); + char sep = ' '; + for (int i = 1;i <= len;i++) { + sb.append(sep).append("($").append(2 * i - 1).append("::int,$").append(2 * i).append("::int)"); + sep = ','; + } + sb.append(") AS update_data (id, randomNumber) WHERE world.id = update_data.id"); + return sb.toString(); } private static Handler> onSuccess(Handler handler) { @@ -259,7 +294,7 @@ private void handleDb(HttpServerRequest req) { .putHeader(HttpHeaders.SERVER, SERVER) .putHeader(HttpHeaders.DATE, dateString) .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(Json.encode(new World(row.getInteger(0), row.getInteger(1))), NULL_HANDLER); + .end(new World(row.getInteger(0), row.getInteger(1)).toBuffer(), NULL_HANDLER); } else { sendError(req, res.cause()); } @@ -269,19 +304,22 @@ private void handleDb(HttpServerRequest req) { class Queries implements Handler>> { boolean failed; - JsonArray worlds = new JsonArray(); + final JsonArray worlds; final HttpServerRequest req; final HttpServerResponse resp; final int queries; public Queries(HttpServerRequest req) { + int queries = getQueries(req); + this.req = req; this.resp = req.response(); - this.queries = getQueries(req); + this.queries = queries; + this.worlds = new JsonArray(new ArrayList<>(queries)); } private void handle() { - client.group(c -> { + client1.group(c -> { for (int i = 0; i < queries; i++) { c.preparedQuery(SELECT_WORLD).execute(Tuple.of(randomWorld()), this); } @@ -299,7 +337,7 @@ public void handle(AsyncResult> ar) { // we need a final reference final Tuple row = ar.result().iterator().next(); - worlds.add(new JsonObject().put("id", "" + row.getInteger(0)).put("randomNumber", "" + row.getInteger(1))); + worlds.add(new JsonObject().put("id", row.getInteger(0)).put("randomNumber", row.getInteger(1))); // stop condition if (worlds.size() == queries) { @@ -307,7 +345,7 @@ public void handle(AsyncResult> ar) { .putHeader(HttpHeaders.SERVER, SERVER) .putHeader(HttpHeaders.DATE, dateString) .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(worlds.encode(), NULL_HANDLER); + .end(worlds.toBuffer(), NULL_HANDLER); } } } @@ -328,7 +366,7 @@ public Update(HttpServerRequest req) { private void handle() { - client.group(c -> { + client1.group(c -> { PreparedQuery> preparedQuery = c.preparedQuery(SELECT_WORLD); for (int i = 0; i < worlds.length; i++) { int id = randomWorld(); @@ -352,42 +390,53 @@ private void handle() { void handleUpdates() { Arrays.sort(worlds); - List batch = new ArrayList<>(); - for (World world : worlds) { - batch.add(Tuple.of(world.getRandomNumber(), world.getId())); - } - UPDATE_WORLD_QUERY.executeBatch(batch, ar2 -> { - if (ar2.failed()) { - sendError(req, ar2.cause()); - return; + int len = worlds.length; + if (0 < len && len <= AGGREGATED_UPDATE_WORLD_QUERY.length) { + List arguments = new ArrayList<>(); + for (World world : worlds) { + arguments.add(world.getId()); + arguments.add(world.getRandomNumber()); } - JsonArray json = new JsonArray(); + Tuple tuple = Tuple.tuple(arguments); + PreparedQuery> query = AGGREGATED_UPDATE_WORLD_QUERY[len - 1]; + query.execute(tuple, this::sendResponse); + } else { + List batch = new ArrayList<>(); for (World world : worlds) { - json.add(new JsonObject().put("id", "" + world.getId()).put("randomNumber", "" + world.getRandomNumber())); + batch.add(Tuple.of(world.getRandomNumber(), world.getId())); } - req.response() - .putHeader(HttpHeaders.SERVER, SERVER) - .putHeader(HttpHeaders.DATE, dateString) - .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(json.toBuffer(), NULL_HANDLER); - }); + UPDATE_WORLD_QUERY.executeBatch(batch, this::sendResponse); + } } + + private void sendResponse(AsyncResult res) { + if (res.failed()) { + sendError(req, res.cause()); + return; + } + JsonArray json = new JsonArray(); + for (World world : worlds) { + json.add(world); + } + req.response() + .putHeader(HttpHeaders.SERVER, SERVER) + .putHeader(HttpHeaders.DATE, dateString) + .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) + .end(json.toBuffer(), NULL_HANDLER); + } + } private void handleFortunes(HttpServerRequest req) { SELECT_FORTUNE_QUERY.execute(ar -> { HttpServerResponse response = req.response(); if (ar.succeeded()) { - List fortunes = new ArrayList<>(); - RowIterator resultSet = ar.result().iterator(); - if (!resultSet.hasNext()) { + SqlResult> result = ar.result(); + if (result.size() == 0) { response.setStatusCode(404).end("No results"); return; } - while (resultSet.hasNext()) { - Row row = resultSet.next(); - fortunes.add(new Fortune(row.getInteger(0), row.getString(1))); - } + List fortunes = result.value(); fortunes.add(new Fortune(0, "Additional fortune added at request time.")); Collections.sort(fortunes); response @@ -412,12 +461,8 @@ private void handleCaching(HttpServerRequest req) { } count = Math.max(1, count); count = Math.min(500, count); - CachedWorld[] worlds = WORLD_CACHE.getCachedWorld(count); - JsonArray json = new JsonArray(new ArrayList<>(count)); - for (int i = 0;i < count;i++) { - CachedWorld world = worlds[i]; - json.add(JsonObject.of("id", world.getId(), "randomNumber", world.getRandomNumber())); - } + List worlds = WORLD_CACHE.getCachedWorld(count); + JsonArray json = new JsonArray(worlds); HttpServerResponse response = req.response(); MultiMap headers = response.headers(); headers @@ -429,7 +474,7 @@ private void handleCaching(HttpServerRequest req) { public static void main(String[] args) throws Exception { - int eventLoopPoolSize = VertxOptions.DEFAULT_EVENT_LOOP_POOL_SIZE; + int eventLoopPoolSize = Runtime.getRuntime().availableProcessors(); String sizeProp = System.getProperty("vertx.eventLoopPoolSize"); if (sizeProp != null) { try { diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java b/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java index b369cc824da..f27e8805f33 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java @@ -1,9 +1,13 @@ package vertx.model; +import io.vertx.core.json.JsonObject; + +import java.util.Map; + /** * The model for the "world" database table. */ -public final class CachedWorld implements Comparable { +public final class CachedWorld extends JsonObject implements Comparable { private final int id; private final int randomNumber; @@ -15,6 +19,7 @@ public final class CachedWorld implements Comparable { * @param randomNumber the random number of the world */ public CachedWorld(int id, int randomNumber) { + super(Map.of("id", id, "randomNumber", randomNumber)); this.id = id; this.randomNumber = randomNumber; } diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/World.java b/frameworks/Java/vertx/src/main/java/vertx/model/World.java index e733b265d65..86f4d29e99b 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/World.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/World.java @@ -1,9 +1,13 @@ package vertx.model; +import io.vertx.core.json.JsonObject; + +import java.util.Map; + /** * The model for the "world" database table. */ -public final class World implements Comparable { +public final class World extends JsonObject implements Comparable { private final int id; private final int randomNumber; @@ -15,6 +19,7 @@ public final class World implements Comparable { * @param randomNumber the random number of the world */ public World(int id, int randomNumber) { + super(Map.of("id", id, "randomNumber", randomNumber)); this.id = id; this.randomNumber = randomNumber; } diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/WorldCache.java b/frameworks/Java/vertx/src/main/java/vertx/model/WorldCache.java index c4d4b150283..2b0d4ae869c 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/WorldCache.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/WorldCache.java @@ -3,6 +3,7 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; @@ -19,12 +20,12 @@ public WorldCache(List worlds) { this.cache = cache; } - public CachedWorld[] getCachedWorld(int count) { - CachedWorld[] ret = new CachedWorld[count]; + public List getCachedWorld(int count) { + List ret = new ArrayList<>(count); ThreadLocalRandom current = ThreadLocalRandom.current(); for (int i = 0;i < count;i++) { Integer key = Integer.valueOf(current.nextInt(1000)); - ret[i] = cache.getIfPresent(key); + ret.add(cache.getIfPresent(key)); } return ret; } diff --git a/frameworks/Java/vertx/src/main/templates/vertx/FortunesTemplate.rocker.html b/frameworks/Java/vertx/src/main/templates/vertx/FortunesTemplate.rocker.html index 4a76266c344..8ceb4d68c7e 100644 --- a/frameworks/Java/vertx/src/main/templates/vertx/FortunesTemplate.rocker.html +++ b/frameworks/Java/vertx/src/main/templates/vertx/FortunesTemplate.rocker.html @@ -1,18 +1,8 @@ @import vertx.model.Fortune @import java.util.List @args(List fortunes) - - -Fortunes - - - - - - @for ((ForIterator i, Fortune fortune) : fortunes) { - - - - }
idmessage
@fortune.getId()@fortune.getMessage()
- - +Fortunes +@for ((ForIterator i, Fortune fortune) : fortunes) { + +} +
idmessage
@fortune.getId()@fortune.getMessage()
\ No newline at end of file From 82a228956c3aeebaa029b5464146330c0cab09c4 Mon Sep 17 00:00:00 2001 From: robert engels Date: Mon, 8 Jul 2024 10:29:46 -0500 Subject: [PATCH 26/62] optimized Java framework based on JDK supplied HTTP server (#9148) * dev environment * production * update README * update for latest httpserver --- frameworks/C++/libsniper/libs/core | 1 + frameworks/Java/httpserver-robaho/README.md | 32 ++++ .../httpserver-robaho/benchmark_config.json | 44 ++++++ frameworks/Java/httpserver-robaho/config.toml | 27 ++++ .../httpserver-robaho-postgres.dockerfile | 13 ++ .../httpserver-robaho.dockerfile | 13 ++ frameworks/Java/httpserver-robaho/pom.xml | 83 +++++++++++ .../src/main/java/benchmarks/Fortune.java | 25 ++++ .../src/main/java/benchmarks/Message.java | 26 ++++ .../src/main/java/benchmarks/Server.java | 139 ++++++++++++++++++ .../src/main/resources/fortunes.template.httl | 13 ++ 11 files changed, 416 insertions(+) create mode 160000 frameworks/C++/libsniper/libs/core create mode 100755 frameworks/Java/httpserver-robaho/README.md create mode 100755 frameworks/Java/httpserver-robaho/benchmark_config.json create mode 100644 frameworks/Java/httpserver-robaho/config.toml create mode 100644 frameworks/Java/httpserver-robaho/httpserver-robaho-postgres.dockerfile create mode 100644 frameworks/Java/httpserver-robaho/httpserver-robaho.dockerfile create mode 100644 frameworks/Java/httpserver-robaho/pom.xml create mode 100644 frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Fortune.java create mode 100755 frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Message.java create mode 100755 frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Server.java create mode 100644 frameworks/Java/httpserver-robaho/src/main/resources/fortunes.template.httl diff --git a/frameworks/C++/libsniper/libs/core b/frameworks/C++/libsniper/libs/core new file mode 160000 index 00000000000..a792ecfebb0 --- /dev/null +++ b/frameworks/C++/libsniper/libs/core @@ -0,0 +1 @@ +Subproject commit a792ecfebb02f98bbdd8db232fba69f3f92907b3 diff --git a/frameworks/Java/httpserver-robaho/README.md b/frameworks/Java/httpserver-robaho/README.md new file mode 100755 index 00000000000..9317e30ce2d --- /dev/null +++ b/frameworks/Java/httpserver-robaho/README.md @@ -0,0 +1,32 @@ +# httpserver Benchmarking Test + +This is an alternative version of the [httpserver benchmarking test suite](../httpserver) + +Package [robaho.net.httpserver](https://github.com/robaho/httpserver) provides an implementation of `com.sun.net.httpserver` designed for virtual threads, thus requiring JDK21+. + +It can be used with platform threads using a `cached thread pool` which configures a thread per task, which is more efficient for a small number of clients (embedded systems). + +### Test Type Implementation Source Code + +* [JSON](src/main/java/benchmarks/Server.java) +* [Plaintext](src/main/java/benchmarks/Server.java) +* [Fortunes](src/main/java/benchmarks/Server.java) + +## Important Libraries +The tests were run with: +* [Jackson](https://github.com/FasterXML/jackson) +* [HikariCP](https://github.com/brettwooldridge/HikariCP) +* [HTTL](https://httl.github.io/en/) + +## Test URLs +### JSON + +http://localhost:8080/json + +### Plaintext + +http://localhost:8080/plaintext + +### Fortunes + +http://localhost:8080/fortunes diff --git a/frameworks/Java/httpserver-robaho/benchmark_config.json b/frameworks/Java/httpserver-robaho/benchmark_config.json new file mode 100755 index 00000000000..e3a66134723 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/benchmark_config.json @@ -0,0 +1,44 @@ +{ + "framework": "httpserver-robaho", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "None", + "framework": "None", + "language": "Java", + "flavor": "None", + "orm": "Raw", + "platform": "httpserver", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "httpserver-robaho", + "notes": "", + "versus": "" + }, + "postgres": { + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "framework": "None", + "language": "Java", + "flavor": "None", + "orm": "Raw", + "platform": "httpserver", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "httpserver-robaho-postgres", + "notes": "", + "versus": "" + } + } + ] +} diff --git a/frameworks/Java/httpserver-robaho/config.toml b/frameworks/Java/httpserver-robaho/config.toml new file mode 100644 index 00000000000..e69305d162c --- /dev/null +++ b/frameworks/Java/httpserver-robaho/config.toml @@ -0,0 +1,27 @@ +[framework] +name = "httpserver-robaho" + +[main] +urls.plaintext = "/plaintext" +urls.json = "/json" +approach = "Realistic" +classification = "Platform" +database = "None" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "httpserver" +webserver = "None" +versus = "" + +[postgres] +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Platform" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Raw" +platform = "httpserver" +webserver = "None" +versus = "" diff --git a/frameworks/Java/httpserver-robaho/httpserver-robaho-postgres.dockerfile b/frameworks/Java/httpserver-robaho/httpserver-robaho-postgres.dockerfile new file mode 100644 index 00000000000..858df742cc8 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/httpserver-robaho-postgres.dockerfile @@ -0,0 +1,13 @@ +FROM jelastic/maven:3.9.5-openjdk-21 as maven +WORKDIR /httpserver-robaho +COPY pom.xml pom.xml +COPY src src +RUN mvn compile assembly:single -q + +FROM openjdk:21-jdk-slim +WORKDIR /httpserver-robaho +COPY --from=maven /httpserver-robaho/target/httpserver-robaho-1.0-jar-with-dependencies.jar app.jar + +EXPOSE 8080 + +CMD ["java", "-server", "-jar", "app.jar", "postgres"] diff --git a/frameworks/Java/httpserver-robaho/httpserver-robaho.dockerfile b/frameworks/Java/httpserver-robaho/httpserver-robaho.dockerfile new file mode 100644 index 00000000000..d02bada7709 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/httpserver-robaho.dockerfile @@ -0,0 +1,13 @@ +FROM jelastic/maven:3.9.5-openjdk-21 as maven +WORKDIR /httpserver-robaho +COPY pom.xml pom.xml +COPY src src +RUN mvn compile assembly:single -q + +FROM openjdk:21-jdk-slim +WORKDIR /httpserver-robaho +COPY --from=maven /httpserver-robaho/target/httpserver-robaho-1.0-jar-with-dependencies.jar app.jar + +EXPOSE 8080 + +CMD ["java", "-server", "-jar", "app.jar"] diff --git a/frameworks/Java/httpserver-robaho/pom.xml b/frameworks/Java/httpserver-robaho/pom.xml new file mode 100644 index 00000000000..ce9dc2cd27e --- /dev/null +++ b/frameworks/Java/httpserver-robaho/pom.xml @@ -0,0 +1,83 @@ + + 4.0.0 + com.techempower + httpserver-robaho + 1.0 + jar + + UTF-8 + 21 + 21 + 21 + + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + org.postgresql + postgresql + 42.7.2 + + + com.zaxxer + HikariCP + 3.3.1 + + + com.github.httl + httl + 1.0.11 + + + org.slf4j + slf4j-simple + 1.7.25 + + + io.github.robaho + httpserver + 1.0.6 + compile + + + + + + true + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + false + + + + maven-assembly-plugin + 3.1.0 + + + + benchmarks.Server + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + diff --git a/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Fortune.java b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Fortune.java new file mode 100644 index 00000000000..2b420fb4764 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Fortune.java @@ -0,0 +1,25 @@ +package benchmarks; + +public class Fortune implements Comparable { + + private final int id; + private final String message; + + public Fortune(int id, String message) { + this.id = id; + this.message = message; + } + + public int getId() { + return id; + } + + public String getMessage() { + return message; + } + + @Override + public int compareTo(Fortune other) { + return message.compareTo(other.message); + } +} diff --git a/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Message.java b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Message.java new file mode 100755 index 00000000000..4c1ad6dc031 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Message.java @@ -0,0 +1,26 @@ +package benchmarks; + +import java.io.IOException; +import java.io.Writer; +import java.util.Map; + +import org.json.simple.JSONStreamAware; +import org.json.simple.JSONValue; + +public class Message implements JSONStreamAware { + + private final String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + @Override + public void writeJSONString(Writer out) throws IOException { + JSONValue.writeJSONString(Map.of("message",message), out); + } +} diff --git a/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Server.java b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Server.java new file mode 100755 index 00000000000..338200488d0 --- /dev/null +++ b/frameworks/Java/httpserver-robaho/src/main/java/benchmarks/Server.java @@ -0,0 +1,139 @@ +package benchmarks; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.net.InetSocketAddress; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executors; + +import javax.sql.DataSource; + +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; + +import httl.Engine; +import httl.Template; + +public class Server { + + private static final String HELLO_TEXT = "Hello, World!"; + private static final byte[] HELLO_BYTES = HELLO_TEXT.getBytes(); + private static final int HELLO_LENGTH = HELLO_BYTES.length; + private static final String SERVER_NAME = "httpserver-robaho"; + + private static List queryFortunes(DataSource ds) throws SQLException { + List fortunes = new ArrayList<>(); + try (Connection conn = ds.getConnection(); + PreparedStatement statement = conn.prepareStatement("SELECT id, message FROM fortune"); + ResultSet resultSet = statement.executeQuery()) { + while (resultSet.next()) + fortunes.add(new Fortune(resultSet.getInt(1), resultSet.getString(2))); + } + return fortunes; + } + + private static DataSource createPostgresDataSource() throws ClassNotFoundException { + Class.forName("org.postgresql.Driver"); + HikariConfig config = new HikariConfig(); + config.setJdbcUrl("jdbc:postgresql://tfb-database:5432/hello_world"); + config.setUsername("benchmarkdbuser"); + config.setPassword("benchmarkdbpass"); + config.setMaximumPoolSize(512); + return new HikariDataSource(config); + } + + private static Template loadTemplate(String filename) throws IOException, ParseException { + Properties props = new Properties(); + props.put("import.packages", "java.util," + Fortune.class.getPackage().getName()); + props.put("input.encoding", "UTF-8"); + props.put("output.encoding", "UTF-8"); + props.put("precompiled", "false"); + Engine engine = Engine.getEngine(props); + return engine.getTemplate(filename); + } + + private static HttpHandler createPlaintextHandler() { + return t -> { + t.getResponseHeaders().add("Content-Type", "text/plain"); + t.getResponseHeaders().add("Server", SERVER_NAME); + t.sendResponseHeaders(200, HELLO_LENGTH); + t.getResponseBody().write(HELLO_BYTES); + t.getResponseBody().close(); + }; + } + + private static HttpHandler createJSONHandler() { + return t -> { + Message m = new Message(HELLO_TEXT); + t.getResponseHeaders().add("Content-Type", "application/json"); + t.getResponseHeaders().add("Server", SERVER_NAME); + var bos = new ByteArrayOutputStream(); + OutputStreamWriter w = new OutputStreamWriter(bos); + m.writeJSONString(w); + w.flush(); + t.sendResponseHeaders(200, bos.size()); + bos.writeTo(t.getResponseBody()); + t.getResponseBody().close(); + }; + } + + private static HttpHandler createFortunesHandler(DataSource ds) throws IOException, ParseException { + Template template = loadTemplate("/fortunes.template.httl"); + return t -> { + try { + // query db + List fortunes = queryFortunes(ds); + fortunes.add(new Fortune(0, "Additional fortune added at request time.")); + Collections.sort(fortunes); + // render template + Map context = new HashMap<>(1); + context.put("fortunes", fortunes); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + template.render(context, out); + byte[] bytes = out.toByteArray(); + // send response + t.getResponseHeaders().add("Content-Type", "text/html; charset=utf-8"); + t.getResponseHeaders().add("Server", SERVER_NAME); + t.sendResponseHeaders(200, bytes.length); + t.getResponseBody().write(bytes); + t.getResponseBody().close(); + } catch (SQLException | ParseException e) { + throw new IOException(e); + } + }; + } + + public static void main(String[] args) throws Exception { + // parse arguments + String settings = args.length > 0 ? args[0] : ""; + int port = args.length > 1 ? Integer.parseInt(args[1]) : 8080; + if (settings.contains("debug")) + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "DEBUG"); + // create server + HttpServer server = HttpServer.create(new InetSocketAddress(port), 1024 * 8); + server.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); + // server.setExecutor(Executors.newCachedThreadPool()); + // add context handlers + server.createContext("/plaintext", createPlaintextHandler()); + server.createContext("/json", createJSONHandler()); + if (settings.contains("postgres")) { + DataSource ds = createPostgresDataSource(); + server.createContext("/fortunes", createFortunesHandler(ds)); + } + // start server + server.start(); + } +} diff --git a/frameworks/Java/httpserver-robaho/src/main/resources/fortunes.template.httl b/frameworks/Java/httpserver-robaho/src/main/resources/fortunes.template.httl new file mode 100644 index 00000000000..4d87b47658a --- /dev/null +++ b/frameworks/Java/httpserver-robaho/src/main/resources/fortunes.template.httl @@ -0,0 +1,13 @@ + + + +Fortunes + + + + + + +
idmessage
${fortune.id}${fortune.message}
+ + From e9e401d678462395e1788a704e240d36279a0a08 Mon Sep 17 00:00:00 2001 From: uNetworkingAB <110806833+uNetworkingAB@users.noreply.github.com> Date: Mon, 8 Jul 2024 17:37:25 +0200 Subject: [PATCH 27/62] uWS.js is Platform (#9058) --- frameworks/JavaScript/uwebsockets.js/benchmark_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/uwebsockets.js/benchmark_config.json b/frameworks/JavaScript/uwebsockets.js/benchmark_config.json index c19862c849e..fee055f341a 100644 --- a/frameworks/JavaScript/uwebsockets.js/benchmark_config.json +++ b/frameworks/JavaScript/uwebsockets.js/benchmark_config.json @@ -4,7 +4,7 @@ { "default": { "approach": "Realistic", - "classification": "Micro", + "classification": "Platform", "database": "None", "database_os": "Linux", "display_name": "uWebSockets.js", From 8cad8194b9937da46411e3f7a67b18201cccd867 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Mon, 8 Jul 2024 17:40:29 +0200 Subject: [PATCH 28/62] [ruby] Use relative path to jemalloc (#9030) This makes sure it works on m1/m2 architecture as well. Linux is capable of resolving the path to the library. --- frameworks/Ruby/agoo/agoo.dockerfile | 2 +- frameworks/Ruby/grape/grape-unicorn.dockerfile | 5 +++++ frameworks/Ruby/grape/grape.dockerfile | 5 +++++ frameworks/Ruby/hanami/hanami.dockerfile | 2 +- .../Ruby/rack-sequel/rack-sequel-passenger-mri.dockerfile | 2 +- .../rack-sequel-postgres-passenger-mri.dockerfile | 2 +- .../rack-sequel-postgres-unicorn-mri.dockerfile | 2 +- .../Ruby/rack-sequel/rack-sequel-postgres.dockerfile | 2 +- .../Ruby/rack-sequel/rack-sequel-unicorn-mri.dockerfile | 2 +- frameworks/Ruby/rack-sequel/rack-sequel.dockerfile | 2 +- frameworks/Ruby/rack/rack-falcon.dockerfile | 2 +- frameworks/Ruby/rack/rack-unicorn.dockerfile | 2 +- frameworks/Ruby/rack/rack.dockerfile | 7 ++++++- frameworks/Ruby/rails/rails-mysql.dockerfile | 2 +- frameworks/Ruby/rails/rails.dockerfile | 2 +- .../Ruby/roda-sequel/roda-sequel-passenger-mri.dockerfile | 2 +- .../roda-sequel-postgres-passenger-mri.dockerfile | 2 +- .../roda-sequel-postgres-unicorn-mri.dockerfile | 2 +- .../Ruby/roda-sequel/roda-sequel-postgres.dockerfile | 2 +- .../Ruby/roda-sequel/roda-sequel-unicorn-mri.dockerfile | 2 +- frameworks/Ruby/roda-sequel/roda-sequel.dockerfile | 2 +- .../Ruby/sinatra-sequel/sinatra-sequel-base.dockerfile | 5 +++++ .../sinatra-sequel/sinatra-sequel-passenger-mri.dockerfile | 5 +++++ .../sinatra-sequel-postgres-passenger-mri.dockerfile | 5 +++++ .../sinatra-sequel-postgres-unicorn-mri.dockerfile | 5 +++++ .../Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile | 5 +++++ .../sinatra-sequel/sinatra-sequel-unicorn-mri.dockerfile | 5 +++++ frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile | 5 +++++ frameworks/Ruby/sinatra/sinatra-passenger-mri.dockerfile | 2 +- .../Ruby/sinatra/sinatra-postgres-passenger-mri.dockerfile | 2 +- .../Ruby/sinatra/sinatra-postgres-unicorn-mri.dockerfile | 2 +- frameworks/Ruby/sinatra/sinatra-postgres.dockerfile | 2 +- frameworks/Ruby/sinatra/sinatra-unicorn-mri.dockerfile | 2 +- frameworks/Ruby/sinatra/sinatra.dockerfile | 2 +- 34 files changed, 75 insertions(+), 25 deletions(-) diff --git a/frameworks/Ruby/agoo/agoo.dockerfile b/frameworks/Ruby/agoo/agoo.dockerfile index bb4e363b687..c8c08141281 100644 --- a/frameworks/Ruby/agoo/agoo.dockerfile +++ b/frameworks/Ruby/agoo/agoo.dockerfile @@ -11,7 +11,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 WORKDIR /rack diff --git a/frameworks/Ruby/grape/grape-unicorn.dockerfile b/frameworks/Ruby/grape/grape-unicorn.dockerfile index 3cc4c7d2d37..f805021f71e 100644 --- a/frameworks/Ruby/grape/grape-unicorn.dockerfile +++ b/frameworks/Ruby/grape/grape-unicorn.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.3 ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + RUN apt-get update -yqq && apt-get install -yqq nginx ADD ./ /grape diff --git a/frameworks/Ruby/grape/grape.dockerfile b/frameworks/Ruby/grape/grape.dockerfile index 5beaf426ddd..99898d43e65 100644 --- a/frameworks/Ruby/grape/grape.dockerfile +++ b/frameworks/Ruby/grape/grape.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.3 ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /grape WORKDIR /grape diff --git a/frameworks/Ruby/hanami/hanami.dockerfile b/frameworks/Ruby/hanami/hanami.dockerfile index 01972160167..6ba8e69f3e6 100644 --- a/frameworks/Ruby/hanami/hanami.dockerfile +++ b/frameworks/Ruby/hanami/hanami.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 WORKDIR /hanami diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-passenger-mri.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-passenger-mri.dockerfile index 7b82353185d..9482a004540 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-passenger-mri.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-passenger-mri.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-postgres-passenger-mri.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-postgres-passenger-mri.dockerfile index 78053b6f376..2765c0c4f89 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-postgres-passenger-mri.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-postgres-passenger-mri.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-postgres-unicorn-mri.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-postgres-unicorn-mri.dockerfile index a3aca7b79bc..37ce2662e7b 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-postgres-unicorn-mri.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-postgres-unicorn-mri.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile index 8033d74c31a..37634239c37 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-postgres.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack-sequel/rack-sequel-unicorn-mri.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel-unicorn-mri.dockerfile index 6df05c0c2b6..67ef3768e71 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel-unicorn-mri.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel-unicorn-mri.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile index 470d92aa4b3..2c7ee155a56 100644 --- a/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile +++ b/frameworks/Ruby/rack-sequel/rack-sequel.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 RUN bundle install --jobs=4 --gemfile=/rack-sequel/Gemfile diff --git a/frameworks/Ruby/rack/rack-falcon.dockerfile b/frameworks/Ruby/rack/rack-falcon.dockerfile index ef5a63a10e7..f6ba1a106a2 100644 --- a/frameworks/Ruby/rack/rack-falcon.dockerfile +++ b/frameworks/Ruby/rack/rack-falcon.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 WORKDIR /rack diff --git a/frameworks/Ruby/rack/rack-unicorn.dockerfile b/frameworks/Ruby/rack/rack-unicorn.dockerfile index bc4807e5427..8609febfd7b 100644 --- a/frameworks/Ruby/rack/rack-unicorn.dockerfile +++ b/frameworks/Ruby/rack/rack-unicorn.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 WORKDIR /rack diff --git a/frameworks/Ruby/rack/rack.dockerfile b/frameworks/Ruby/rack/rack.dockerfile index 5b51b2ef1e0..e40bfced37a 100644 --- a/frameworks/Ruby/rack/rack.dockerfile +++ b/frameworks/Ruby/rack/rack.dockerfile @@ -1,12 +1,17 @@ FROM ruby:3.4-rc -ENV BUNDLE_FORCE_RUBY_PLATFORM=true ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + WORKDIR /rack COPY Gemfile ./ +ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle config set without 'development test' RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/rails/rails-mysql.dockerfile b/frameworks/Ruby/rails/rails-mysql.dockerfile index a93f26b52da..ae512cbdafd 100644 --- a/frameworks/Ruby/rails/rails-mysql.dockerfile +++ b/frameworks/Ruby/rails/rails-mysql.dockerfile @@ -10,7 +10,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 COPY ./Gemfile* /rails/ diff --git a/frameworks/Ruby/rails/rails.dockerfile b/frameworks/Ruby/rails/rails.dockerfile index 9d75f7d359e..99c16e935bb 100644 --- a/frameworks/Ruby/rails/rails.dockerfile +++ b/frameworks/Ruby/rails/rails.dockerfile @@ -9,7 +9,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 COPY ./Gemfile* /rails/ diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-passenger-mri.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-passenger-mri.dockerfile index 0af00a72d36..e25f21e20d9 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-passenger-mri.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-passenger-mri.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-passenger-mri.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-passenger-mri.dockerfile index a24b9881d00..b3f87e9c742 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-passenger-mri.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-passenger-mri.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-unicorn-mri.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-unicorn-mri.dockerfile index 3cde40eaa97..4865d5feebd 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres-unicorn-mri.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres-unicorn-mri.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile index c74c9b9f0d3..d71a4b28a78 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-postgres.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel-unicorn-mri.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel-unicorn-mri.dockerfile index cda64c5c29b..d0cd81077bb 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel-unicorn-mri.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel-unicorn-mri.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile index efa9d35597e..382f31291a1 100644 --- a/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile +++ b/frameworks/Ruby/roda-sequel/roda-sequel.dockerfile @@ -8,7 +8,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ENV BUNDLE_FORCE_RUBY_PLATFORM=true RUN bundle install --jobs=8 diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-base.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-base.dockerfile index 4fe264d4cb6..942d363b75c 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-base.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-base.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.4-rc ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-passenger-mri.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-passenger-mri.dockerfile index fe497718534..39bd11758da 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-passenger-mri.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-passenger-mri.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.3 ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-passenger-mri.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-passenger-mri.dockerfile index 74defc8326e..5651c491808 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-passenger-mri.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-passenger-mri.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.3 ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-unicorn-mri.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-unicorn-mri.dockerfile index 939eb97fce5..4d03257046a 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-unicorn-mri.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres-unicorn-mri.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.4-rc ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile index ab54544763d..77a2801d16d 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-postgres.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.3 ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-unicorn-mri.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-unicorn-mri.dockerfile index 78e45656c51..c3e2bc7de13 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel-unicorn-mri.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel-unicorn-mri.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.4-rc ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile index e36c111221c..80198c299ab 100644 --- a/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile +++ b/frameworks/Ruby/sinatra-sequel/sinatra-sequel.dockerfile @@ -2,6 +2,11 @@ FROM ruby:3.4-rc ENV RUBY_YJIT_ENABLE=1 +# Use Jemalloc +RUN apt-get update && \ + apt-get install -y --no-install-recommends libjemalloc2 +ENV LD_PRELOAD=libjemalloc.so.2 + ADD ./ /sinatra-sequel WORKDIR /sinatra-sequel diff --git a/frameworks/Ruby/sinatra/sinatra-passenger-mri.dockerfile b/frameworks/Ruby/sinatra/sinatra-passenger-mri.dockerfile index df0ddd1fa46..eb07d7b5ba7 100644 --- a/frameworks/Ruby/sinatra/sinatra-passenger-mri.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-passenger-mri.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra diff --git a/frameworks/Ruby/sinatra/sinatra-postgres-passenger-mri.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres-passenger-mri.dockerfile index 0ad6b16252b..2a09b22aeba 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres-passenger-mri.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres-passenger-mri.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra diff --git a/frameworks/Ruby/sinatra/sinatra-postgres-unicorn-mri.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres-unicorn-mri.dockerfile index a38a0456218..027a5593040 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres-unicorn-mri.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres-unicorn-mri.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra diff --git a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile index 69ec07037dd..6258ac08c7d 100644 --- a/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-postgres.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra diff --git a/frameworks/Ruby/sinatra/sinatra-unicorn-mri.dockerfile b/frameworks/Ruby/sinatra/sinatra-unicorn-mri.dockerfile index 76ca52267f1..f0dede838aa 100644 --- a/frameworks/Ruby/sinatra/sinatra-unicorn-mri.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra-unicorn-mri.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra diff --git a/frameworks/Ruby/sinatra/sinatra.dockerfile b/frameworks/Ruby/sinatra/sinatra.dockerfile index 85fe69e9b73..8e204def810 100644 --- a/frameworks/Ruby/sinatra/sinatra.dockerfile +++ b/frameworks/Ruby/sinatra/sinatra.dockerfile @@ -5,7 +5,7 @@ ENV RUBY_YJIT_ENABLE=1 # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 -ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 +ENV LD_PRELOAD=libjemalloc.so.2 ADD ./ /sinatra WORKDIR /sinatra From 158bd471ded84bb53c0b258601d32d7b4b4cd9fe Mon Sep 17 00:00:00 2001 From: Nathan Ortega Date: Mon, 8 Jul 2024 11:49:32 -0400 Subject: [PATCH 29/62] [New Framework]: Oxygen.jl (#8789) * added Oxygen.jl example with /plaintext and /json tests * renamed framework from oxygen-jl to oxygen * renamed top level directory to match framework name * updated readme --- frameworks/Julia/oxygen/README.md | 21 +++++++++++++++ frameworks/Julia/oxygen/benchmark_config.json | 26 +++++++++++++++++++ frameworks/Julia/oxygen/oxygen.dockerfile | 8 ++++++ frameworks/Julia/oxygen/src/Project.toml | 4 +++ frameworks/Julia/oxygen/src/server.jl | 23 ++++++++++++++++ 5 files changed, 82 insertions(+) create mode 100755 frameworks/Julia/oxygen/README.md create mode 100755 frameworks/Julia/oxygen/benchmark_config.json create mode 100644 frameworks/Julia/oxygen/oxygen.dockerfile create mode 100644 frameworks/Julia/oxygen/src/Project.toml create mode 100644 frameworks/Julia/oxygen/src/server.jl diff --git a/frameworks/Julia/oxygen/README.md b/frameworks/Julia/oxygen/README.md new file mode 100755 index 00000000000..5b7ac109195 --- /dev/null +++ b/frameworks/Julia/oxygen/README.md @@ -0,0 +1,21 @@ +# Oxygen.jl Benchmarking Test + +Oxygen is a micro-framework built on top of the HTTP.jl library and comes with helpful utilities to quickly setup and run web applications in Julia. + +### Test Type Implementation Source Code + +* [JSON](Relative/Path/To/Your/Source/File) +* [PLAINTEXT](Relative/Path/To/Your/Source/File) + +## Important Libraries +The tests were run with: +* [Oxygen.jl](https://github.com/OxygenFramework/Oxygen.jl) + +## Test URLs +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext diff --git a/frameworks/Julia/oxygen/benchmark_config.json b/frameworks/Julia/oxygen/benchmark_config.json new file mode 100755 index 00000000000..e998bb13773 --- /dev/null +++ b/frameworks/Julia/oxygen/benchmark_config.json @@ -0,0 +1,26 @@ +{ + "framework": "oxygen", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "None", + "database": "None", + "framework": "Oxygen.jl", + "language": "Julia", + "orm": "None", + "platform": "None", + "webserver": "Oxygen.jl", + "os": "Linux", + "database_os": "Linux", + "display_name": "Oxygen.jl", + "notes": "", + "versus": "", + "tags": [] + } + } + ] +} \ No newline at end of file diff --git a/frameworks/Julia/oxygen/oxygen.dockerfile b/frameworks/Julia/oxygen/oxygen.dockerfile new file mode 100644 index 00000000000..df34f0a4b38 --- /dev/null +++ b/frameworks/Julia/oxygen/oxygen.dockerfile @@ -0,0 +1,8 @@ +FROM julia:latest + +WORKDIR /app +COPY ./src ./ +RUN julia --project -e 'using Pkg; Pkg.instantiate()' + +EXPOSE 8080 +CMD julia -t 2 --project server.jl \ No newline at end of file diff --git a/frameworks/Julia/oxygen/src/Project.toml b/frameworks/Julia/oxygen/src/Project.toml new file mode 100644 index 00000000000..dbe190679c2 --- /dev/null +++ b/frameworks/Julia/oxygen/src/Project.toml @@ -0,0 +1,4 @@ +[deps] +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +Oxygen = "df9a0d86-3283-4920-82dc-4555fc0d1d8b" diff --git a/frameworks/Julia/oxygen/src/server.jl b/frameworks/Julia/oxygen/src/server.jl new file mode 100644 index 00000000000..e88c1669472 --- /dev/null +++ b/frameworks/Julia/oxygen/src/server.jl @@ -0,0 +1,23 @@ + +using Oxygen +using Dates +using HTTP + +@get "/json" function() + return json(("message" => "Hello, World!")) +end + +@get "/plaintext" function() + return text("Hello, World!") +end + +function HeaderMiddleware(handle::Function) + function(req::HTTP.Request) + response = handle(req) + HTTP.setheader(response, "Server" => "Julia-Oxygen") + HTTP.setheader(response, "Date" => Dates.format(Dates.now(), Dates.RFC1123Format) * " GMT") + return response + end +end + +serveparallel(host="0.0.0.0", port=8080, middleware=[HeaderMiddleware], access_log=nothing, metrics=false, docs=false) \ No newline at end of file From 31ca740439ca9ebe3e80d72818421e0cffea647f Mon Sep 17 00:00:00 2001 From: Shagit Ziganshin <3687591+theLastOfCats@users.noreply.github.com> Date: Mon, 8 Jul 2024 19:28:30 +0300 Subject: [PATCH 30/62] [swift|vapor] Added Vapor+Swifql+Ikiga (#9146) * Added Vapor+Swifql+Ikiga (cherry picked from commit cf1fc17c508024927d35ca5da15aab1fa85d20ad) * Fixes so everything compiles * Another attempt at fixes * Removed unsupported @retroactive * Added db benchmark * FoundationEssentials JSON Coders support * Added everything else * Remove ikiga * remove FoundationPreview due to bug https://github.com/apple/swift-foundation/issues/715 * fix db hostname * fix fortune template * last fixes * fixed resources * hb2 compiles successfully * hb2-postgres compiles --------- Co-authored-by: Shagit Ziganshin Co-authored-by: Yakov Shapovalov --- .../Controllers/FortunesController.swift | 2 +- .../src-postgres/Sources/server/main.swift | 11 +- .../src/Sources/server/main.swift | 11 +- frameworks/Swift/vapor/benchmark_config.json | 23 ++++ frameworks/Swift/vapor/config.toml | 17 +++ .../Swift/vapor/vapor-swifql.dockerfile | 30 ++++ .../Swift/vapor/vapor-swifql/.dockerignore | 2 + .../Swift/vapor/vapor-swifql/.gitignore | 14 ++ .../Swift/vapor/vapor-swifql/Package.swift | 46 +++++++ .../vapor-swifql/Resources/Views/fortune.leaf | 10 ++ .../IkigaJSONCoders+ContentCoders.swift | 56 ++++++++ .../Sources/Extensions/Models+Content.swift | 11 ++ .../Sources/Extensions/Utils.swift | 18 +++ .../vapor-swifql/Sources/Models/Fortune.swift | 17 +++ .../vapor-swifql/Sources/Models/World.swift | 11 ++ .../vapor-swifql/Sources/configure.swift | 128 ++++++++++++++++++ .../vapor/vapor-swifql/Sources/main.swift | 16 +++ 17 files changed, 418 insertions(+), 5 deletions(-) create mode 100644 frameworks/Swift/vapor/vapor-swifql.dockerfile create mode 100644 frameworks/Swift/vapor/vapor-swifql/.dockerignore create mode 100644 frameworks/Swift/vapor/vapor-swifql/.gitignore create mode 100644 frameworks/Swift/vapor/vapor-swifql/Package.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Resources/Views/fortune.leaf create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/IkigaJSONCoders+ContentCoders.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Models+Content.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Utils.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/Models/Fortune.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/Models/World.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/configure.swift create mode 100644 frameworks/Swift/vapor/vapor-swifql/Sources/main.swift diff --git a/frameworks/Swift/hummingbird2/src-postgres/Sources/server/Controllers/FortunesController.swift b/frameworks/Swift/hummingbird2/src-postgres/Sources/server/Controllers/FortunesController.swift index 159901dda40..cd8012c6d26 100644 --- a/frameworks/Swift/hummingbird2/src-postgres/Sources/server/Controllers/FortunesController.swift +++ b/frameworks/Swift/hummingbird2/src-postgres/Sources/server/Controllers/FortunesController.swift @@ -4,7 +4,7 @@ import PostgresNIO struct HTML: ResponseGenerator, Sendable { let html: String - public func response(from request: Request, context: some BaseRequestContext) -> Response { + public func response(from request: Request, context: some RequestContext) -> Response { let buffer = context.allocator.buffer(string: html) return Response(status: .ok, headers: [.contentType: "text/html; charset=utf-8"], body: .init(byteBuffer: buffer)) } diff --git a/frameworks/Swift/hummingbird2/src-postgres/Sources/server/main.swift b/frameworks/Swift/hummingbird2/src-postgres/Sources/server/main.swift index 65e360bfab3..772a52a5430 100644 --- a/frameworks/Swift/hummingbird2/src-postgres/Sources/server/main.swift +++ b/frameworks/Swift/hummingbird2/src-postgres/Sources/server/main.swift @@ -1,3 +1,4 @@ +import Foundation import Hummingbird import PostgresNIO @@ -15,15 +16,21 @@ struct TechFrameworkRequestContext: RequestContext { static let jsonEncoder = JSONEncoder() static let jsonDecoder = JSONDecoder() - var coreContext: Hummingbird.CoreRequestContext + var coreContext: Hummingbird.CoreRequestContextStorage // Use a global JSON Encoder var responseEncoder: JSONEncoder { Self.jsonEncoder } // Use a global JSON Decoder var requestDecoder: JSONDecoder { Self.jsonDecoder } + init(source: ApplicationRequestContextSource) { + self.init(channel: source.channel, logger: source.logger) + } + init(channel: any Channel, logger: Logger) { - self.coreContext = .init(allocator: channel.allocator, logger: logger) + self.coreContext = CoreRequestContextStorage( + source: ApplicationRequestContextSource(channel: channel, logger: logger) + ) } } diff --git a/frameworks/Swift/hummingbird2/src/Sources/server/main.swift b/frameworks/Swift/hummingbird2/src/Sources/server/main.swift index f652046a166..365b9a6a58f 100644 --- a/frameworks/Swift/hummingbird2/src/Sources/server/main.swift +++ b/frameworks/Swift/hummingbird2/src/Sources/server/main.swift @@ -1,4 +1,6 @@ +import Foundation import Hummingbird +import HummingbirdCore import Logging import NIOCore @@ -7,18 +9,23 @@ struct Object: ResponseEncodable { } struct TechFrameworkRequestContext: RequestContext { + static let jsonEncoder = JSONEncoder() static let jsonDecoder = JSONDecoder() - var coreContext: Hummingbird.CoreRequestContext + var coreContext: Hummingbird.CoreRequestContextStorage // Use a global JSON Encoder var responseEncoder: JSONEncoder { Self.jsonEncoder } // Use a global JSON Decoder var requestDecoder: JSONDecoder { Self.jsonDecoder } + init(source: Hummingbird.ApplicationRequestContextSource) { + self.coreContext = CoreRequestContextStorage(source: ApplicationRequestContextSource(channel: source.channel, logger: source.logger)) + } + init(channel: any Channel, logger: Logger) { - self.coreContext = .init(allocator: channel.allocator, logger: logger) + self.coreContext = CoreRequestContextStorage(source: ApplicationRequestContextSource(channel: channel, logger: logger)) } } diff --git a/frameworks/Swift/vapor/benchmark_config.json b/frameworks/Swift/vapor/benchmark_config.json index 1bd0d8e2242..00b6bb943dc 100755 --- a/frameworks/Swift/vapor/benchmark_config.json +++ b/frameworks/Swift/vapor/benchmark_config.json @@ -93,6 +93,29 @@ "display_name": "Vapor", "notes": "", "versus": "None" + }, + "swifql": { + "plaintext_url": "/plaintext", + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "database": "Postgres", + "orm": "Micro", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "framework": "Vapor", + "language": "Swift", + "flavor": "None", + "platform": "None", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Vapor", + "notes": "", + "versus": "None" } }] } diff --git a/frameworks/Swift/vapor/config.toml b/frameworks/Swift/vapor/config.toml index e629702ef66..24db8e89c90 100644 --- a/frameworks/Swift/vapor/config.toml +++ b/frameworks/Swift/vapor/config.toml @@ -51,3 +51,20 @@ orm = "Micro" platform = "None" webserver = "None" versus = "None" + +[swifql] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/queries?queries=" +urls.update = "/updates?queries=" +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Fullstack" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Micro" +platform = "None" +webserver = "None" +versus = "None" \ No newline at end of file diff --git a/frameworks/Swift/vapor/vapor-swifql.dockerfile b/frameworks/Swift/vapor/vapor-swifql.dockerfile new file mode 100644 index 00000000000..d39373d63a6 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql.dockerfile @@ -0,0 +1,30 @@ +# ================================ +# Build image +# ================================ +FROM swift:5.10 as build +WORKDIR /build + +# Copy entire repo into container +COPY ./vapor-swifql . + +# Compile with optimizations +RUN swift build \ + -c release \ + -Xswiftc -enforce-exclusivity=unchecked + +# ================================ +# Run image +# ================================ +FROM swift:5.10-slim +WORKDIR /run + +# Copy build artifacts +COPY --from=build /build/.build/release /run +COPY ./vapor-swifql/Resources/Views/fortune.leaf /run/Resources/Views/fortune.leaf + +# Copy Swift runtime libraries +COPY --from=build /usr/lib/swift/ /usr/lib/swift/ + +EXPOSE 8080 + +ENTRYPOINT ["./app", "serve", "--env", "production", "--hostname", "0.0.0.0", "--port", "8080"] diff --git a/frameworks/Swift/vapor/vapor-swifql/.dockerignore b/frameworks/Swift/vapor/vapor-swifql/.dockerignore new file mode 100644 index 00000000000..2d9f16e2d27 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/.dockerignore @@ -0,0 +1,2 @@ +.build/ +.swiftpm/ diff --git a/frameworks/Swift/vapor/vapor-swifql/.gitignore b/frameworks/Swift/vapor/vapor-swifql/.gitignore new file mode 100644 index 00000000000..1f4d514fd4c --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/.gitignore @@ -0,0 +1,14 @@ +Packages +.build +xcuserdata +*.xcodeproj +DerivedData/ +.DS_Store +db.sqlite +.swiftpm +.env +.env.* +! .env.example +.vscode +docker-compose.yml +Dockerfile \ No newline at end of file diff --git a/frameworks/Swift/vapor/vapor-swifql/Package.swift b/frameworks/Swift/vapor/vapor-swifql/Package.swift new file mode 100644 index 00000000000..43d9104cecd --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Package.swift @@ -0,0 +1,46 @@ +// swift-tools-version:5.10 + +import PackageDescription + +let package = Package( + name: "vapor-swifql-ikiga", + platforms: [ + .macOS(.v12) + ], + products: [ + .executable(name: "app", targets: ["App"]) + ], + dependencies: [ + // 💧 A server-side Swift web framework. + .package(url: "https://github.com/vapor/vapor.git", from: "4.99.3"), + .package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"), + // 🔵 Non-blocking, event-driven networking for Swift. Used for custom executors + .package(url: "https://github.com/apple/swift-nio.git", from: "2.65.0"), + // json encoder/decoder + .package(url: "https://github.com/orlandos-nl/IkigaJSON.git", from: "2.0.0"), + // sql builder + .package(url: "https://github.com/SwifQL/VaporBridges.git", from: "1.0.0-rc"), + .package(url: "https://github.com/SwifQL/PostgresBridge.git", from: "1.0.0-rc"), + ], + targets: [ + .executableTarget( + name: "App", + dependencies: [ + .product(name: "Vapor", package: "vapor"), + .product(name: "Leaf", package: "leaf"), + .product(name: "NIOCore", package: "swift-nio"), + .product(name: "NIOPosix", package: "swift-nio"), + .product(name: "VaporBridges", package: "VaporBridges"), + .product(name: "PostgresBridge", package: "PostgresBridge"), + .product(name: "IkigaJSON", package: "IkigaJSON"), + ], + swiftSettings: swiftSettings + ) + ] +) + +var swiftSettings: [SwiftSetting] { [ + .enableUpcomingFeature("DisableOutwardActorInference"), + .enableExperimentalFeature("StrictConcurrency"), + .unsafeFlags(["-parse-as-library"]), +] } diff --git a/frameworks/Swift/vapor/vapor-swifql/Resources/Views/fortune.leaf b/frameworks/Swift/vapor/vapor-swifql/Resources/Views/fortune.leaf new file mode 100644 index 00000000000..020d76adc92 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Resources/Views/fortune.leaf @@ -0,0 +1,10 @@ + + +Fortunes + + + +#for(fortune in fortunes): +#endfor
idmessage
#(fortune.id)#(fortune.message)
+ + \ No newline at end of file diff --git a/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/IkigaJSONCoders+ContentCoders.swift b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/IkigaJSONCoders+ContentCoders.swift new file mode 100644 index 00000000000..676ff7285b6 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/IkigaJSONCoders+ContentCoders.swift @@ -0,0 +1,56 @@ +// +// IkigaJSONCoders+ContentCoders.swift +// +// +// Created by Yakov Shapovalov on 04.07.2024. +// + +import IkigaJSON +import Vapor + +extension IkigaJSONEncoder: ContentEncoder { + public func encode( + _ encodable: E, + to body: inout ByteBuffer, + headers: inout HTTPHeaders + ) throws { + headers.contentType = .json + try self.encodeAndWrite(encodable, into: &body) + } + + public func encode(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws where E : Encodable { + var encoder = self + encoder.userInfo = userInfo + headers.contentType = .json + try encoder.encodeAndWrite(encodable, into: &body) + } + + public func encode(_ encodable: E, to body: inout ByteBuffer, headers: inout HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws where E : Encodable { + var encoder = self + encoder.userInfo = userInfo + headers.contentType = .json + try encoder.encodeAndWrite(encodable, into: &body) + } +} + +extension IkigaJSONDecoder: ContentDecoder { + public func decode( + _ decodable: D.Type, + from body: ByteBuffer, + headers: HTTPHeaders + ) throws -> D { + return try self.decode(D.self, from: body) + } + + public func decode(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Sendable]) throws -> D where D : Decodable { + let decoder = IkigaJSONDecoder(settings: settings) + decoder.settings.userInfo = userInfo + return try decoder.decode(D.self, from: body) + } + + public func decode(_ decodable: D.Type, from body: ByteBuffer, headers: HTTPHeaders, userInfo: [CodingUserInfoKey : Any]) throws -> D where D : Decodable { + let decoder = IkigaJSONDecoder(settings: settings) + decoder.settings.userInfo = userInfo + return try decoder.decode(D.self, from: body) + } +} diff --git a/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Models+Content.swift b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Models+Content.swift new file mode 100644 index 00000000000..8fdae4b378f --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Models+Content.swift @@ -0,0 +1,11 @@ +// +// Models+Content.swift +// +// +// Created by Yakov Shapovalov on 04.07.2024. +// + +import Vapor + +extension World: Content {} +extension Fortune: Content {} diff --git a/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Utils.swift b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Utils.swift new file mode 100644 index 00000000000..d370b15e291 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Sources/Extensions/Utils.swift @@ -0,0 +1,18 @@ +extension Int { + func bounded(to range: ClosedRange) -> Int { + switch self { + case ...range.lowerBound: + return range.lowerBound + case range.upperBound...: + return range.upperBound + default: + return self + } + } +} + +extension Int: Sequence { + public func makeIterator() -> CountableRange.Iterator { + return (0.. World in + guard let world: World = try await req.postgres.connection(to: .Db, { conn in + World.select + .where(\World.$id == Int.random(in: 1...10_000)) + .execute(on: conn) + .first(decoding: World.self) + }).get() else { + throw Abort(.notFound) + } + return world + } + + app.get("queries") { req async throws -> [World] in + let queries: Int = (req.query["queries"] ?? 1).bounded(to: 1...500) + + var worlds: [World] = [] + + for _ in queries { + guard let world: World = try await req.postgres.connection(to: .Db, { conn in + World.select + .where(\World.$id == Int.random(in: 1...10_000)) + .execute(on: conn) + .first(decoding: World.self) + }).get() else { + throw Abort(.notFound) + } + + worlds.append(world) + } + return worlds + } + + app.get("updates") { req async throws -> [World] in + let queries = (req.query["queries"] ?? 1).bounded(to: 1...500) + + var worlds: [World] = [] + + for _ in queries { + let world = try await req.postgres.connection(to: .Db, { conn in + World.select.where(\World.$id == Int.random(in: 1...10_000)).execute(on: conn).first(decoding: World.self).flatMap { world in + world!.randomnumber = .random(in: 1...10_000) + return world!.update(on: \.$id, on: conn) + } + }).get() + + worlds.append(world) + } + + return worlds + + } + + app.get("fortunes") { req async throws -> View in + var fortunes: [Fortune] = try await req.postgres.connection(to: .Db, {conn in + Fortune.select.execute(on: conn).all(decoding: Fortune.self) + }) + .get() + + fortunes.append(Fortune(id: 0, message: "Additional fortune added at request time.")) + + fortunes.sort(by: { + $0.message < $1.message + }) + + return try await req.view.render("fortune", ["fortunes": fortunes]) + } +} + diff --git a/frameworks/Swift/vapor/vapor-swifql/Sources/main.swift b/frameworks/Swift/vapor/vapor-swifql/Sources/main.swift new file mode 100644 index 00000000000..81feddfbc02 --- /dev/null +++ b/frameworks/Swift/vapor/vapor-swifql/Sources/main.swift @@ -0,0 +1,16 @@ +import Vapor +import PostgresBridge +import Logging + +@main +enum App { + static func main() throws { + var env = try Environment.detect() + try LoggingSystem.bootstrap(from: &env) + + let app = Application(env) + defer { app.shutdown() } + + try configure(app) + } +} From 3a6fcdbbb38025e59c16e5a92b1b4e3c49647413 Mon Sep 17 00:00:00 2001 From: uNetworkingAB <110806833+uNetworkingAB@users.noreply.github.com> Date: Mon, 8 Jul 2024 19:33:49 +0200 Subject: [PATCH 31/62] [uwebsockets.js] Use faster plaintext response, update version (#9056) --- frameworks/JavaScript/uwebsockets.js/package-lock.json | 6 +++--- frameworks/JavaScript/uwebsockets.js/package.json | 2 +- frameworks/JavaScript/uwebsockets.js/src/server.js | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/frameworks/JavaScript/uwebsockets.js/package-lock.json b/frameworks/JavaScript/uwebsockets.js/package-lock.json index 275f2f63b2e..910703e95b8 100644 --- a/frameworks/JavaScript/uwebsockets.js/package-lock.json +++ b/frameworks/JavaScript/uwebsockets.js/package-lock.json @@ -12,7 +12,7 @@ "mariadb": "^3.3.0", "postgres": "^3.4.4", "slow-json-stringify": "^2.0.1", - "uWebSockets.js": "uNetworking/uWebSockets.js#v20.43.0" + "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" } }, "node_modules/@types/geojson": { @@ -98,8 +98,8 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/uWebSockets.js": { - "version": "20.31.0", - "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#809b99d2d7d12e2cbf89b7135041e9b41ff84084" + "version": "20.44.0", + "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#8fa05571bf6ea95be8966ad313d9d39453e381ae" } } } diff --git a/frameworks/JavaScript/uwebsockets.js/package.json b/frameworks/JavaScript/uwebsockets.js/package.json index c64742e442d..ec5bc0c1d73 100644 --- a/frameworks/JavaScript/uwebsockets.js/package.json +++ b/frameworks/JavaScript/uwebsockets.js/package.json @@ -3,7 +3,7 @@ "mariadb": "^3.3.0", "postgres": "^3.4.4", "slow-json-stringify": "^2.0.1", - "uWebSockets.js": "uNetworking/uWebSockets.js#v20.43.0" + "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" }, "license": "MIT", "main": "src/server.js", diff --git a/frameworks/JavaScript/uwebsockets.js/src/server.js b/frameworks/JavaScript/uwebsockets.js/src/server.js index f67f33e874b..1db7d391f2a 100644 --- a/frameworks/JavaScript/uwebsockets.js/src/server.js +++ b/frameworks/JavaScript/uwebsockets.js/src/server.js @@ -16,11 +16,11 @@ if (DATABASE) db = await import(`./database/${DATABASE}.js`); const webserver = uWebSockets.App(); -webserver.get("/plaintext", (response) => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "text/plain"); - response.end("Hello, World!"); -}); +webserver.get("/plaintext", new uWebSockets.DeclarativeResponse() + .writeHeader("Server", "uWebSockets.js") + .writeHeader("Content-Type", "text/plain") + .end("Hello, World!") +); webserver.get("/json", (response) => { addBenchmarkHeaders(response); From 63f467e295b3f722dd850d2e064a1211447e3580 Mon Sep 17 00:00:00 2001 From: Bartosz Jarzyna <44323413+bbrtj@users.noreply.github.com> Date: Tue, 9 Jul 2024 20:01:54 +0200 Subject: [PATCH 32/62] Perl: Fix non-functional benchmarks (#9151) * Perl: unify the maximum requests per child value * Fix Perl Dancer * Fix Perl Web::Simple * Fix Perl Plack * Fix Perl Mojolicious * Perl Kelp: provide a default benchmark to silence the warning * Perl Mojolicious: minor adjustments --- frameworks/Perl/dancer/README.md | 3 +- frameworks/Perl/dancer/app.pl | 7 +- frameworks/Perl/dancer/benchmark_config.json | 3 +- frameworks/Perl/dancer/dancer.dockerfile | 7 +- frameworks/Perl/kelp/benchmark_config.json | 2 +- frameworks/Perl/kelp/run.pl | 4 + frameworks/Perl/mojolicious/app.pl | 116 +++---- frameworks/Perl/mojolicious/cpanfile | 3 +- frameworks/Perl/mojolicious/cpanfile.snapshot | 319 +++++++++--------- .../Perl/mojolicious/mojolicious.dockerfile | 3 +- frameworks/Perl/plack/README.md | 3 +- frameworks/Perl/plack/app-async.psgi | 3 +- frameworks/Perl/plack/app.pl | 4 +- frameworks/Perl/plack/app.psgi | 5 +- frameworks/Perl/plack/plack-async.dockerfile | 3 +- frameworks/Perl/plack/plack.dockerfile | 3 +- frameworks/Perl/web-simple/README.md | 3 +- frameworks/Perl/web-simple/app.pl | 3 +- .../Perl/web-simple/benchmark_config.json | 3 +- .../Perl/web-simple/web-simple.dockerfile | 6 +- 20 files changed, 256 insertions(+), 247 deletions(-) diff --git a/frameworks/Perl/dancer/README.md b/frameworks/Perl/dancer/README.md index c2afcf7639c..56b1d27d773 100644 --- a/frameworks/Perl/dancer/README.md +++ b/frameworks/Perl/dancer/README.md @@ -8,7 +8,7 @@ * Dancer * Dancer::Plugin::Database -* DBD::mysql +* DBD::MariaDB * Starman (if using Starman as web server) * Plack (for plackup) * nginx (if you want to front Dancer with nginx, nginx.conf provided) @@ -22,3 +22,4 @@ Something along the lines of if you want to front it with nginx, otherwise plackup -E production -s Starman --port=8080 --workers=2 -a ./app.pl + diff --git a/frameworks/Perl/dancer/app.pl b/frameworks/Perl/dancer/app.pl index dd58de39896..65ab9d2a6a3 100755 --- a/frameworks/Perl/dancer/app.pl +++ b/frameworks/Perl/dancer/app.pl @@ -8,8 +8,8 @@ set serializer => 'JSON'; -my $dsn = "dbi:mysql:database=hello_world;host=tfb-database;port=3306"; -my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', { mysql_auto_reconnect=>1 } ); +my $dsn = "dbi:MariaDB:database=hello_world;host=tfb-database;port=3306"; +my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass' ); my $sth = $dbh->prepare("SELECT * FROM World where id = ?"); get '/json' => sub { @@ -20,7 +20,7 @@ my $queries = params->{queries} || 1; $queries = 1 if ( $queries !~ /^\d+$/ || $queries < 1 ); $queries = 500 if $queries > 500; - + my @response; for ( 1 .. $queries ) { my $id = int rand 10000 + 1; @@ -42,3 +42,4 @@ }; Dancer->dance; + diff --git a/frameworks/Perl/dancer/benchmark_config.json b/frameworks/Perl/dancer/benchmark_config.json index 94408b910f7..306909555ae 100644 --- a/frameworks/Perl/dancer/benchmark_config.json +++ b/frameworks/Perl/dancer/benchmark_config.json @@ -19,7 +19,8 @@ "display_name": "dancer", "notes": "", "versus": "", - "tags": ["broken"] + "tags": [] } }] } + diff --git a/frameworks/Perl/dancer/dancer.dockerfile b/frameworks/Perl/dancer/dancer.dockerfile index 687c3825ae9..0094ff8fca8 100644 --- a/frameworks/Perl/dancer/dancer.dockerfile +++ b/frameworks/Perl/dancer/dancer.dockerfile @@ -1,4 +1,4 @@ -FROM perl:5.26 +FROM perl:5.40 RUN apt-get update -yqq && apt-get install -yqq nginx @@ -10,7 +10,7 @@ RUN cpanm --notest --no-man-page \ Dancer@1.3134 \ Dancer::Plugin::Database@2.10 \ DBI@1.633 \ - DBD::mysql@4.033 \ + DBD::MariaDB@1.23 \ JSON::XS@3.01 \ Plack@1.0034 \ Starman@0.4011 @@ -18,4 +18,5 @@ RUN cpanm --notest --no-man-page \ EXPOSE 8080 CMD nginx -c /dancer/nginx.conf && \ - plackup -E production -s Starman --workers=$(nproc) -l /tmp/perl-dancer.sock -a ./app.pl + plackup -E production -s Starman --workers=$(nproc) --max-requests=100000 -l /tmp/perl-dancer.sock -a ./app.pl + diff --git a/frameworks/Perl/kelp/benchmark_config.json b/frameworks/Perl/kelp/benchmark_config.json index 1cd06f51ad0..dc164a11576 100644 --- a/frameworks/Perl/kelp/benchmark_config.json +++ b/frameworks/Perl/kelp/benchmark_config.json @@ -1,7 +1,7 @@ { "framework": "kelp", "tests": [{ - "gazelle-mysql": { + "default": { "dockerfile": "kelp.dockerfile", "plaintext_url": "/plaintext", "json_url": "/json", diff --git a/frameworks/Perl/kelp/run.pl b/frameworks/Perl/kelp/run.pl index b8436498f64..3aaed8d4cf7 100755 --- a/frameworks/Perl/kelp/run.pl +++ b/frameworks/Perl/kelp/run.pl @@ -62,6 +62,10 @@ ], ); +# default is gazelle-mysql (techempower will warn if there is no default) +$test_name = 'kelp-gazelle-mysql' + if $test_name eq 'kelp'; + die "invalid test name $test_name" unless $test_name =~ m{^kelp-(\w+)-(\w+)$}; diff --git a/frameworks/Perl/mojolicious/app.pl b/frameworks/Perl/mojolicious/app.pl index a1e38dd48f6..465c2c7381c 100644 --- a/frameworks/Perl/mojolicious/app.pl +++ b/frameworks/Perl/mojolicious/app.pl @@ -1,18 +1,19 @@ +use v5.36; use Mojolicious::Lite; use Mojo::Pg; use Mojo::Promise; -use Cpanel::JSON::XS 'encode_json'; use Scalar::Util 'looks_like_number'; -use Data::Dumper; # configuration +use constant MAX_DB_CONCURRENCY => 50; + { my $nproc = `nproc`; app->config(hypnotoad => { - accepts => 0, - clients => int( 256 / $nproc ) + 1, + accepts => 100000, + clients => MAX_DB_CONCURRENCY, graceful_timeout => 1, requests => 10000, workers => $nproc, @@ -20,41 +21,33 @@ }); } -{ - my $db_host = 'tfb-database'; - helper pg => sub { state $pg = Mojo::Pg->new('postgresql://benchmarkdbuser:benchmarkdbpass@' . $db_host . '/hello_world')->max_connections(50) }; -} - -helper render_json => sub { - my $c = shift; - $c->res->headers->content_type('application/json'); - $c->render( data => encode_json(shift) ); -}; - # Routes -get '/json' => sub { shift->helpers->render_json({message => 'Hello, World!'}) }; +get '/json' => sub ($c) { + $c->render(json => {message => 'Hello, World!'}); +}; -get '/db' => sub { shift->helpers->render_query(1, {single => 1}) }; +get '/db' => sub ($c) { + $c->helpers->render_query(1, {single => 1}); +}; -get '/queries' => sub { - my $c = shift; +get '/queries' => sub ($c) { $c->helpers->render_query(scalar $c->param('queries')); }; -get '/fortunes' => sub { - my $c = shift; +get '/fortunes' => sub ($c) { $c->render_later; - my $docs = $c->helpers->pg->db->query_p('SELECT id, message FROM Fortune') - ->then(sub{ - my $docs = $_[0]->arrays; - push @$docs, [0, 'Additional fortune added at request time.']; - $c->render(fortunes => docs => $docs->sort(sub{ $a->[1] cmp $b->[1] }) ) - }); + + $c->helpers->pg->db->query_p('SELECT id, message FROM Fortune') + ->then(sub ($query) { + my $docs = $query->arrays; + push @$docs, [0, 'Additional fortune added at request time.']; + + $c->render(fortunes => docs => $docs->sort(sub { $a->[1] cmp $b->[1] })); + }); }; -get '/updates' => sub { - my $c = shift; +get '/updates' => sub ($c) { $c->helpers->render_query(scalar $c->param('queries'), {update => 1}); }; @@ -62,55 +55,47 @@ # Additional helpers (shared code) -helper 'render_query' => sub { - my ($self, $q, $args) = @_; +helper pg => sub { + state $pg = Mojo::Pg + ->new('postgresql://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world') + ->max_connections(MAX_DB_CONCURRENCY + 1); +}; + +helper 'render_query' => sub ($self, $q, $args = {}) { $self->render_later; - $args ||= {}; - my $update = $args->{update}; $q = 1 unless looks_like_number($q); $q = 1 if $q < 1; $q = 500 if $q > 500; - my $r = []; - my $tx = $self->tx; + Mojo::Promise->map({concurrency => MAX_DB_CONCURRENCY}, sub { + my $db = $self->helpers->pg->db; + my $id = 1 + int rand 10_000; + my $query = $db->query('SELECT id, randomnumber FROM World WHERE id=?', $id); + my $number = $query->array->[1]; - my @queries; - foreach (1 .. $q) { - my $id = 1 + int rand 10_000; + if ($args->{update}) { + $number = 1 + int rand 10_000; + $db->query('UPDATE World SET randomnumber=? WHERE id=?', $number, $id); + } - push @queries, $self->helpers->pg->db->query_p('SELECT id,randomnumber FROM World WHERE id=?', $id) - ->then(sub{ - my $randomNumber = $_[0]->array->[0]; - - return Mojo::Promise->new->resolve($id, $randomNumber) - ->then(sub{ - if($update) { - $randomNumber = 1 + int rand 10_000; - return Mojo::Promise->all( - Mojo::Promise->new->resolve($_[0], $randomNumber), - $self->helpers->pg->db->query_p('UPDATE World SET randomnumber=? WHERE id=?', $randomNumber, $id) - ) - ->then(sub { - return $_[0]; - }) - } - return [shift, shift]; - }) - }); - } + return Mojo::Promise->resolve([$id, $number]); + }, 1 .. $q) + ->then(sub (@responses) { + my @results; - Mojo::Promise->all(@queries) - ->then(sub{ - my @responses = @_; foreach my $resp (@responses) { - push @$r, { id => $resp->[0][0], randomNumber => $resp->[0][1] }; + push @results, { id => $resp->[0][0], randomNumber => $resp->[0][1] }; } - $r = $r->[0] if $args->{single}; - $self->helpers->render_json($r); - }) + if ($args->{single}) { + $self->render(json => $results[0]); + } + else { + $self->render(json => \@results); + } + }); }; app->start; @@ -133,3 +118,4 @@ + diff --git a/frameworks/Perl/mojolicious/cpanfile b/frameworks/Perl/mojolicious/cpanfile index 12f340c183e..68299a759ce 100644 --- a/frameworks/Perl/mojolicious/cpanfile +++ b/frameworks/Perl/mojolicious/cpanfile @@ -1,7 +1,8 @@ requires 'Mojolicious', '7.84'; requires 'Mojo::Pg', '4.08'; -requires 'Cpanel::JSON::XS', '4.02'; +requires 'Cpanel::JSON::XS', '4.38'; requires 'EV', '4.22'; recommends 'IO::Socket::IP', '0.36'; recommends 'IO::Socket::SSL'; + diff --git a/frameworks/Perl/mojolicious/cpanfile.snapshot b/frameworks/Perl/mojolicious/cpanfile.snapshot index a43dcb6688e..c3f7c9e074b 100644 --- a/frameworks/Perl/mojolicious/cpanfile.snapshot +++ b/frameworks/Perl/mojolicious/cpanfile.snapshot @@ -1,15 +1,15 @@ # carton snapshot format: version 1.0 DISTRIBUTIONS - Canary-Stability-2012 - pathname: M/ML/MLEHMANN/Canary-Stability-2012.tar.gz + Canary-Stability-2013 + pathname: M/ML/MLEHMANN/Canary-Stability-2013.tar.gz provides: - Canary::Stability 2012 + Canary::Stability 2013 requirements: ExtUtils::MakeMaker 0 - Class-Method-Modifiers-2.12 - pathname: E/ET/ETHER/Class-Method-Modifiers-2.12.tar.gz + Class-Method-Modifiers-2.15 + pathname: E/ET/ETHER/Class-Method-Modifiers-2.15.tar.gz provides: - Class::Method::Modifiers 2.12 + Class::Method::Modifiers 2.15 requirements: B 0 Carp 0 @@ -27,27 +27,36 @@ DISTRIBUTIONS ExtUtils::MakeMaker 0 Storable 0 perl 5.008001 - Cpanel-JSON-XS-4.02 - pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.02.tar.gz + Cpanel-JSON-XS-4.38 + pathname: R/RU/RURBAN/Cpanel-JSON-XS-4.38.tar.gz provides: - Cpanel::JSON::XS 4.02 + Cpanel::JSON::XS 4.38 Cpanel::JSON::XS::Type undef requirements: + Carp 0 + Config 0 + Encode 1.9801 + Exporter 0 ExtUtils::MakeMaker 0 Pod::Text 2.08 - DBD-Pg-3.7.4 - pathname: T/TU/TURNSTEP/DBD-Pg-3.7.4.tar.gz + XSLoader 0 + overload 0 + strict 0 + warnings 0 + DBD-Pg-3.18.0 + pathname: T/TU/TURNSTEP/DBD-Pg-3.18.0.tar.gz provides: - Bundle::DBD::Pg v3.7.4 - DBD::Pg v3.7.4 + Bundle::DBD::Pg v3.18.0 + DBD::Pg v3.18.0 requirements: DBI 1.614 - ExtUtils::MakeMaker 6.11 + ExtUtils::MakeMaker 6.58 + File::Temp 0 Test::More 0.88 Time::HiRes 0 version 0 - DBI-1.641 - pathname: T/TI/TIMB/DBI-1.641.tar.gz + DBI-1.643 + pathname: T/TI/TIMB/DBI-1.643.tar.gz provides: Bundle::DBI 12.008696 DBD::DBM 0.08 @@ -103,7 +112,7 @@ DISTRIBUTIONS DBD::Sponge::dr 12.010003 DBD::Sponge::st 12.010003 DBDI 12.015129 - DBI 1.641 + DBI 1.643 DBI::Const::GetInfo::ANSI 2.008697 DBI::Const::GetInfo::ODBC 2.011374 DBI::Const::GetInfoReturn 2.008697 @@ -143,128 +152,60 @@ DISTRIBUTIONS DBI::SQL::Nano::Table_ 1.015544 DBI::Util::CacheMemory 0.010315 DBI::Util::_accessor 0.009479 - DBI::common 1.641 + DBI::common 1.643 requirements: ExtUtils::MakeMaker 6.48 Test::Simple 0.90 - perl 5.008 - Devel-GlobalDestruction-0.14 - pathname: H/HA/HAARG/Devel-GlobalDestruction-0.14.tar.gz - provides: - Devel::GlobalDestruction 0.14 - requirements: - ExtUtils::MakeMaker 0 - Sub::Exporter::Progressive 0.001011 - perl 5.006 - EV-4.22 - pathname: M/ML/MLEHMANN/EV-4.22.tar.gz + perl 5.008001 + EV-4.34 + pathname: M/ML/MLEHMANN/EV-4.34.tar.gz provides: - EV 4.22 + EV 4.34 EV::MakeMaker undef requirements: Canary::Stability 0 ExtUtils::MakeMaker 6.52 common::sense 0 - Hash-Merge-0.300 - pathname: R/RE/REHSACK/Hash-Merge-0.300.tar.gz + Hash-Merge-0.302 + pathname: H/HE/HERMES/Hash-Merge-0.302.tar.gz provides: - Hash::Merge 0.300 + Hash::Merge 0.302 requirements: Clone::Choose 0.008 ExtUtils::MakeMaker 6.64 Scalar::Util 0 perl 5.008001 - MRO-Compat-0.13 - pathname: H/HA/HAARG/MRO-Compat-0.13.tar.gz + MRO-Compat-0.15 + pathname: H/HA/HAARG/MRO-Compat-0.15.tar.gz provides: - MRO::Compat 0.13 + MRO::Compat 0.15 requirements: ExtUtils::MakeMaker 0 perl 5.006 - Module-Build-0.4224 - pathname: L/LE/LEONT/Module-Build-0.4224.tar.gz - provides: - Module::Build 0.4224 - Module::Build::Base 0.4224 - Module::Build::Compat 0.4224 - Module::Build::Config 0.4224 - Module::Build::Cookbook 0.4224 - Module::Build::Dumper 0.4224 - Module::Build::Notes 0.4224 - Module::Build::PPMMaker 0.4224 - Module::Build::Platform::Default 0.4224 - Module::Build::Platform::MacOS 0.4224 - Module::Build::Platform::Unix 0.4224 - Module::Build::Platform::VMS 0.4224 - Module::Build::Platform::VOS 0.4224 - Module::Build::Platform::Windows 0.4224 - Module::Build::Platform::aix 0.4224 - Module::Build::Platform::cygwin 0.4224 - Module::Build::Platform::darwin 0.4224 - Module::Build::Platform::os2 0.4224 - Module::Build::PodParser 0.4224 - requirements: - CPAN::Meta 2.142060 - CPAN::Meta::YAML 0.003 - Cwd 0 - Data::Dumper 0 - ExtUtils::CBuilder 0.27 - ExtUtils::Install 0 - ExtUtils::Manifest 0 - ExtUtils::Mkbootstrap 0 - ExtUtils::ParseXS 2.21 - File::Basename 0 - File::Compare 0 - File::Copy 0 - File::Find 0 - File::Path 0 - File::Spec 0.82 - File::Temp 0.15 - Getopt::Long 0 - Module::Metadata 1.000002 - Parse::CPAN::Meta 1.4401 - Perl::OSType 1 - Pod::Man 2.17 - TAP::Harness 3.29 - Test::More 0.49 - Text::Abbrev 0 - Text::ParseWords 0 - perl 5.006001 - version 0.87 - Module-Runtime-0.016 - pathname: Z/ZE/ZEFRAM/Module-Runtime-0.016.tar.gz - provides: - Module::Runtime 0.016 - requirements: - Module::Build 0 - Test::More 0.41 - perl 5.006 - strict 0 - warnings 0 - Mojo-Pg-4.08 - pathname: S/SR/SRI/Mojo-Pg-4.08.tar.gz + Mojo-Pg-4.27 + pathname: S/SR/SRI/Mojo-Pg-4.27.tar.gz provides: - Mojo::Pg 4.08 + Mojo::Pg 4.27 Mojo::Pg::Database undef Mojo::Pg::Migrations undef Mojo::Pg::PubSub undef Mojo::Pg::Results undef Mojo::Pg::Transaction undef - SQL::Abstract::Pg undef requirements: - DBD::Pg 3.005001 + DBD::Pg 3.007004 ExtUtils::MakeMaker 0 - Mojolicious 7.53 - SQL::Abstract 1.85 - perl 5.010001 - Mojolicious-7.84 - pathname: S/SR/SRI/Mojolicious-7.84.tar.gz + Mojolicious 8.50 + SQL::Abstract::Pg 1.0 + perl 5.016 + Mojolicious-9.37 + pathname: S/SR/SRI/Mojolicious-9.37.tar.gz provides: Mojo undef Mojo::Asset undef Mojo::Asset::File undef Mojo::Asset::Memory undef Mojo::Base undef + Mojo::BaseUtil undef Mojo::ByteStream undef Mojo::Cache undef Mojo::Collection undef @@ -278,6 +219,7 @@ DISTRIBUTIONS Mojo::DOM::CSS undef Mojo::DOM::HTML undef Mojo::Date undef + Mojo::DynamicMethods undef Mojo::EventEmitter undef Mojo::Exception undef Mojo::File undef @@ -286,13 +228,8 @@ DISTRIBUTIONS Mojo::Home undef Mojo::IOLoop undef Mojo::IOLoop::Client undef - Mojo::IOLoop::Delay undef Mojo::IOLoop::Server undef Mojo::IOLoop::Stream undef - Mojo::IOLoop::Stream::HTTPClient undef - Mojo::IOLoop::Stream::HTTPServer undef - Mojo::IOLoop::Stream::WebSocketClient undef - Mojo::IOLoop::Stream::WebSocketServer undef Mojo::IOLoop::Subprocess undef Mojo::IOLoop::TLS undef Mojo::JSON undef @@ -316,7 +253,6 @@ DISTRIBUTIONS Mojo::Server::Morbo::Backend undef Mojo::Server::Morbo::Backend::Poll undef Mojo::Server::PSGI undef - Mojo::Server::PSGI::_IO undef Mojo::Server::Prefork undef Mojo::Template undef Mojo::Transaction undef @@ -331,37 +267,36 @@ DISTRIBUTIONS Mojo::UserAgent::Transactor undef Mojo::Util undef Mojo::WebSocket undef - Mojolicious 7.84 + Mojolicious 9.37 Mojolicious::Command undef + Mojolicious::Command::Author::cpanify undef + Mojolicious::Command::Author::generate undef + Mojolicious::Command::Author::generate::app undef + Mojolicious::Command::Author::generate::dockerfile undef + Mojolicious::Command::Author::generate::lite_app undef + Mojolicious::Command::Author::generate::makefile undef + Mojolicious::Command::Author::generate::plugin undef + Mojolicious::Command::Author::inflate undef Mojolicious::Command::cgi undef - Mojolicious::Command::cpanify undef Mojolicious::Command::daemon undef Mojolicious::Command::eval undef - Mojolicious::Command::generate undef - Mojolicious::Command::generate::app undef - Mojolicious::Command::generate::lite_app undef - Mojolicious::Command::generate::makefile undef - Mojolicious::Command::generate::plugin undef Mojolicious::Command::get undef - Mojolicious::Command::inflate undef Mojolicious::Command::prefork undef Mojolicious::Command::psgi undef Mojolicious::Command::routes undef - Mojolicious::Command::test undef Mojolicious::Command::version undef Mojolicious::Commands undef Mojolicious::Controller undef Mojolicious::Lite undef Mojolicious::Plugin undef Mojolicious::Plugin::Config undef - Mojolicious::Plugin::Config::Sandbox undef Mojolicious::Plugin::DefaultHelpers undef Mojolicious::Plugin::EPLRenderer undef Mojolicious::Plugin::EPRenderer undef Mojolicious::Plugin::HeaderCondition undef Mojolicious::Plugin::JSONConfig undef Mojolicious::Plugin::Mount undef - Mojolicious::Plugin::PODRenderer undef + Mojolicious::Plugin::NotYAMLConfig undef Mojolicious::Plugin::TagHelpers undef Mojolicious::Plugins undef Mojolicious::Renderer undef @@ -379,52 +314,55 @@ DISTRIBUTIONS requirements: ExtUtils::MakeMaker 0 IO::Socket::IP 0.37 - JSON::PP 2.27103 - Pod::Simple 3.09 - Time::Local 1.2 - perl 5.010001 - Moo-2.003004 - pathname: H/HA/HAARG/Moo-2.003004.tar.gz + Sub::Util 1.41 + perl 5.016 + Moo-2.005005 + pathname: H/HA/HAARG/Moo-2.005005.tar.gz provides: Method::Generate::Accessor undef Method::Generate::BuildAll undef Method::Generate::Constructor undef Method::Generate::DemolishAll undef - Moo 2.003004 + Moo 2.005005 Moo::HandleMoose undef Moo::HandleMoose::FakeConstructor undef Moo::HandleMoose::FakeMetaClass undef Moo::HandleMoose::_TypeMap undef Moo::Object undef - Moo::Role 2.003004 + Moo::Role 2.005005 Moo::_Utils undef - Moo::_mro undef - Moo::_strictures undef Moo::sification undef oo undef requirements: - Class::Method::Modifiers 1.1 - Devel::GlobalDestruction 0.11 - Exporter 5.57 + Carp 0 + Class::Method::Modifiers 1.10 + Exporter 0 ExtUtils::MakeMaker 0 - Module::Runtime 0.014 - Role::Tiny 2.000004 - Scalar::Util 0 - Sub::Defer 2.003001 - Sub::Quote 2.003001 + Role::Tiny 2.002003 + Scalar::Util 1.00 + Sub::Defer 2.006006 + Sub::Quote 2.006006 perl 5.006 - Role-Tiny-2.000006 - pathname: H/HA/HAARG/Role-Tiny-2.000006.tar.gz + Role-Tiny-2.002004 + pathname: H/HA/HAARG/Role-Tiny-2.002004.tar.gz provides: - Role::Tiny 2.000006 - Role::Tiny::With 2.000006 + Role::Tiny 2.002004 + Role::Tiny::With 2.002004 requirements: Exporter 5.57 perl 5.006 - SQL-Abstract-1.85 - pathname: I/IL/ILMARI/SQL-Abstract-1.85.tar.gz + SQL-Abstract-2.000001 + pathname: M/MS/MSTROUT/SQL-Abstract-2.000001.tar.gz provides: - SQL::Abstract 1.85 + Chunkstrumenter undef + DBIx::Class::SQLMaker::Role::SQLA2Passthrough undef + SQL::Abstract 2.000001 + SQL::Abstract::Formatter undef + SQL::Abstract::Parts undef + SQL::Abstract::Plugin::BangOverrides undef + SQL::Abstract::Plugin::ExtraClauses undef + SQL::Abstract::Reference undef + SQL::Abstract::Role::Plugin undef SQL::Abstract::Test undef SQL::Abstract::Tree undef requirements: @@ -436,26 +374,91 @@ DISTRIBUTIONS Moo 2.000001 Scalar::Util 0 Sub::Quote 2.000001 + Test::Builder::Module 0.84 + Test::Deep 0.101 Text::Balanced 2.00 perl 5.006 - Sub-Exporter-Progressive-0.001013 - pathname: F/FR/FREW/Sub-Exporter-Progressive-0.001013.tar.gz + SQL-Abstract-Pg-1.0 + pathname: S/SR/SRI/SQL-Abstract-Pg-1.0.tar.gz provides: - Sub::Exporter::Progressive 0.001013 + SQL::Abstract::Pg 1.0 requirements: ExtUtils::MakeMaker 0 - Sub-Quote-2.005001 - pathname: H/HA/HAARG/Sub-Quote-2.005001.tar.gz + SQL::Abstract 2.0 + perl 5.016 + Sub-Quote-2.006008 + pathname: H/HA/HAARG/Sub-Quote-2.006008.tar.gz provides: - Sub::Defer 2.005001 - Sub::Quote 2.005001 + Sub::Defer 2.006008 + Sub::Quote 2.006008 requirements: ExtUtils::MakeMaker 0 Scalar::Util 0 perl 5.006 - common-sense-3.74 - pathname: M/ML/MLEHMANN/common-sense-3.74.tar.gz + Test-Deep-1.204 + pathname: R/RJ/RJBS/Test-Deep-1.204.tar.gz + provides: + Test::Deep 1.204 + Test::Deep::All 1.204 + Test::Deep::Any 1.204 + Test::Deep::Array 1.204 + Test::Deep::ArrayEach 1.204 + Test::Deep::ArrayElementsOnly 1.204 + Test::Deep::ArrayLength 1.204 + Test::Deep::ArrayLengthOnly 1.204 + Test::Deep::Blessed 1.204 + Test::Deep::Boolean 1.204 + Test::Deep::Cache 1.204 + Test::Deep::Cache::Simple 1.204 + Test::Deep::Class 1.204 + Test::Deep::Cmp 1.204 + Test::Deep::Code 1.204 + Test::Deep::Hash 1.204 + Test::Deep::HashEach 1.204 + Test::Deep::HashElements 1.204 + Test::Deep::HashKeys 1.204 + Test::Deep::HashKeysOnly 1.204 + Test::Deep::Ignore 1.204 + Test::Deep::Isa 1.204 + Test::Deep::ListMethods 1.204 + Test::Deep::MM 1.204 + Test::Deep::Methods 1.204 + Test::Deep::NoTest 1.204 + Test::Deep::None 1.204 + Test::Deep::Number 1.204 + Test::Deep::Obj 1.204 + Test::Deep::Ref 1.204 + Test::Deep::RefType 1.204 + Test::Deep::Regexp 1.204 + Test::Deep::RegexpMatches 1.204 + Test::Deep::RegexpOnly 1.204 + Test::Deep::RegexpRef 1.204 + Test::Deep::RegexpRefOnly 1.204 + Test::Deep::RegexpVersion 1.204 + Test::Deep::ScalarRef 1.204 + Test::Deep::ScalarRefOnly 1.204 + Test::Deep::Set 1.204 + Test::Deep::Shallow 1.204 + Test::Deep::Stack 1.204 + Test::Deep::String 1.204 + Test::Deep::SubHash 1.204 + Test::Deep::SubHashElements 1.204 + Test::Deep::SubHashKeys 1.204 + Test::Deep::SubHashKeysOnly 1.204 + Test::Deep::SuperHash 1.204 + Test::Deep::SuperHashElements 1.204 + Test::Deep::SuperHashKeys 1.204 + Test::Deep::SuperHashKeysOnly 1.204 + requirements: + ExtUtils::MakeMaker 6.78 + List::Util 1.09 + Scalar::Util 1.09 + Test::Builder 0 + Test::More 0.96 + perl 5.012 + common-sense-3.75 + pathname: M/ML/MLEHMANN/common-sense-3.75.tar.gz provides: - common::sense 3.74 + common::sense 3.75 requirements: ExtUtils::MakeMaker 0 diff --git a/frameworks/Perl/mojolicious/mojolicious.dockerfile b/frameworks/Perl/mojolicious/mojolicious.dockerfile index fe9197e6233..1fec0cc3952 100644 --- a/frameworks/Perl/mojolicious/mojolicious.dockerfile +++ b/frameworks/Perl/mojolicious/mojolicious.dockerfile @@ -1,4 +1,4 @@ -FROM perl:5.26 +FROM perl:5.40 WORKDIR /mojo @@ -19,3 +19,4 @@ ADD ./app.pl ./ EXPOSE 8080 CMD hypnotoad -f /mojo/app.pl + diff --git a/frameworks/Perl/plack/README.md b/frameworks/Perl/plack/README.md index f8172775ec1..d08e9a91a20 100644 --- a/frameworks/Perl/plack/README.md +++ b/frameworks/Perl/plack/README.md @@ -9,4 +9,5 @@ Plack * Twiggy::Prefork * JSON::XS * AnyEvent::DBI -* DBD::mysql +* DBD::MariaDB + diff --git a/frameworks/Perl/plack/app-async.psgi b/frameworks/Perl/plack/app-async.psgi index 93df1c50b2d..b5397d1ca5e 100644 --- a/frameworks/Perl/plack/app-async.psgi +++ b/frameworks/Perl/plack/app-async.psgi @@ -5,7 +5,7 @@ use AnyEvent::DBI; use Unix::Processors; use List::Util qw'min max'; -my @dsn = ('dbi:mysql:database=hello_world;host=tfb-database;port=3306', 'benchmarkdbuser', 'benchmarkdbpass'); +my @dsn = ('dbi:MariaDB:database=hello_world;host=tfb-database;port=3306', 'benchmarkdbuser', 'benchmarkdbpass'); my $query = 'select randomNumber, id from World where id = ?'; sub { @@ -37,3 +37,4 @@ sub { } [404, [qw(Content-Type application/json)], ['not found']] } + diff --git a/frameworks/Perl/plack/app.pl b/frameworks/Perl/plack/app.pl index c1a1172b277..b62eaa6acdc 100644 --- a/frameworks/Perl/plack/app.pl +++ b/frameworks/Perl/plack/app.pl @@ -7,10 +7,10 @@ my @cmd = ( ($opts->{a} # async server - ? [qw'plackup -s Twiggy::Prefork -E production --max-reqs-per-child=0 --backlog 16384 + ? [qw'plackup -s Twiggy::Prefork -E production --max-reqs-per-child=100000 --backlog 16384 --max-workers', $cpus, qw'-l /dev/shm/app.sock -a app-async.psgi'] : [qw'start_server --backlog 16384 --path /dev/shm/app.sock -- - plackup -s Gazelle -E production --max-reqs-per-child 10000000 + plackup -s Gazelle -E production --max-reqs-per-child 100000 --max-workers', $cpus, qw'-a app.psgi']), [qw'nginx -c nginx.conf -p', getcwd] ); diff --git a/frameworks/Perl/plack/app.psgi b/frameworks/Perl/plack/app.psgi index 4f5d8579d38..dc625076660 100644 --- a/frameworks/Perl/plack/app.psgi +++ b/frameworks/Perl/plack/app.psgi @@ -5,9 +5,9 @@ use List::Util qw'min max'; sub { state $dbh = DBI->connect( - 'dbi:mysql:database=hello_world;host=tfb-database;port=3306', + 'dbi:MariaDB:database=hello_world;host=tfb-database;port=3306', 'benchmarkdbuser', 'benchmarkdbpass', - +{ qw'RaiseError 0 PrintError 0 mysql_enable_utf8 1' } + +{ qw'RaiseError 0 PrintError 0' } ) || die $!; state $sth = $dbh->prepare('select id,randomnumber from world where id = ?'); my $env = shift; @@ -25,3 +25,4 @@ sub { } [ 404, [], ['not found']]; } + diff --git a/frameworks/Perl/plack/plack-async.dockerfile b/frameworks/Perl/plack/plack-async.dockerfile index 4af66083005..8ef1ac76b04 100644 --- a/frameworks/Perl/plack/plack-async.dockerfile +++ b/frameworks/Perl/plack/plack-async.dockerfile @@ -1,7 +1,7 @@ FROM perl:latest RUN apt-get update -yqq && apt-get install -yqq nginx -RUN cpanm --notest --no-man-page Plack JSON::XS Unix::Processors DBI DBD::mysql +RUN cpanm --notest --no-man-page Plack JSON::XS Unix::Processors DBI DBD::MariaDB RUN cpanm --notest --no-man-page Cookie::Baker::XS Twiggy::Prefork HTTP::Parser::XS EV AnyEvent::DBI ADD nginx.conf ./ @@ -11,3 +11,4 @@ ADD app-async.psgi ./ EXPOSE 8080 CMD perl app.pl -a + diff --git a/frameworks/Perl/plack/plack.dockerfile b/frameworks/Perl/plack/plack.dockerfile index f2a14dd5b4c..a0391f2f4ca 100644 --- a/frameworks/Perl/plack/plack.dockerfile +++ b/frameworks/Perl/plack/plack.dockerfile @@ -1,7 +1,7 @@ FROM perl:latest RUN apt-get update -yqq && apt-get install -yqq nginx -RUN cpanm --notest --no-man-page Plack JSON::XS Unix::Processors DBI DBD::mysql +RUN cpanm --notest --no-man-page Plack JSON::XS Unix::Processors DBI DBD::MariaDB RUN cpanm --notest --no-man-page Gazelle Cookie::Baker::XS ADD nginx.conf ./ @@ -11,3 +11,4 @@ ADD app.psgi ./ EXPOSE 8080 CMD perl app.pl + diff --git a/frameworks/Perl/web-simple/README.md b/frameworks/Perl/web-simple/README.md index d169c515914..98e8d6a836e 100644 --- a/frameworks/Perl/web-simple/README.md +++ b/frameworks/Perl/web-simple/README.md @@ -7,7 +7,7 @@ # Requirements * Web::Simple -* DBD::mysql +* DBD::MariaDB * Starman (if using Starman as web server) * Plack (for plackup) * nginx (if you want to front Dancer with nginx, nginx.conf provided) @@ -21,3 +21,4 @@ Something along the lines of if you want to front it with nginx, otherwise plackup -E production -s Starman --port=8080 --workers=8 -a ./app.pl + diff --git a/frameworks/Perl/web-simple/app.pl b/frameworks/Perl/web-simple/app.pl index d2db3e11299..2447c765c01 100755 --- a/frameworks/Perl/web-simple/app.pl +++ b/frameworks/Perl/web-simple/app.pl @@ -4,7 +4,7 @@ use DBI; sub get_database_handle { - DBI->connect_cached('dbi:mysql:database=hello_world;host=tfb-database', 'benchmarkdbuser', 'benchmarkdbpass', { RaiseError => 1 }); + DBI->connect_cached('dbi:MariaDB:database=hello_world;host=tfb-database', 'benchmarkdbuser', 'benchmarkdbpass', { RaiseError => 1 }); } sub dispatch_request { @@ -54,3 +54,4 @@ sub dispatch_request { } __PACKAGE__->run_if_script; + diff --git a/frameworks/Perl/web-simple/benchmark_config.json b/frameworks/Perl/web-simple/benchmark_config.json index 629b19df0c1..6725005d211 100644 --- a/frameworks/Perl/web-simple/benchmark_config.json +++ b/frameworks/Perl/web-simple/benchmark_config.json @@ -19,7 +19,8 @@ "display_name": "web-simple", "notes": "", "versus": "", - "tags": ["broken"] + "tags": [] } }] } + diff --git a/frameworks/Perl/web-simple/web-simple.dockerfile b/frameworks/Perl/web-simple/web-simple.dockerfile index f3b83b7a7c0..5a2678bfe1b 100644 --- a/frameworks/Perl/web-simple/web-simple.dockerfile +++ b/frameworks/Perl/web-simple/web-simple.dockerfile @@ -1,4 +1,4 @@ -FROM perl:5.26 +FROM perl:5.40 RUN apt-get update -yqq && apt-get install -yqq nginx @@ -8,7 +8,7 @@ RUN cpanm --notest --no-man-page \ JSON JSON::XS IO::Socket::IP IO::Socket::SSL \ Web::Simple@0.033 \ DBI@1.637 \ - DBD::mysql@4.043 \ + DBD::MariaDB@1.23 \ Plack@1.0044 \ Starman@0.4014 \ JSON::XS@3.04 @@ -21,4 +21,6 @@ EXPOSE 8080 CMD nginx -c /simple/nginx.conf && \ plackup -E production -s Starman --workers=$(nproc) \ + --max-requests=100000 \ -l /tmp/perl-simple.sock -a /simple/app.pl + From 411a25b56a646df27a8b4d583b2fb866875308ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:00:04 +0000 Subject: [PATCH 33/62] Bump google.golang.org/grpc in /frameworks/Go/goravel/src/fiber Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.64.0 to 1.64.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.64.0...v1.64.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frameworks/Go/goravel/src/fiber/go.mod | 6 +++--- frameworks/Go/goravel/src/fiber/go.sum | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/Go/goravel/src/fiber/go.mod b/frameworks/Go/goravel/src/fiber/go.mod index e285c0106e3..b31a4b9ba88 100644 --- a/frameworks/Go/goravel/src/fiber/go.mod +++ b/frameworks/Go/goravel/src/fiber/go.mod @@ -4,8 +4,6 @@ go 1.22 require ( github.com/bytedance/sonic v1.11.9 - github.com/gofiber/fiber/v2 v2.52.4 - github.com/gofiber/template/html/v2 v2.1.1 github.com/goravel/fiber v1.2.1 github.com/goravel/framework v1.14.1 github.com/valyala/quicktemplate v1.7.0 @@ -63,7 +61,9 @@ require ( github.com/go-redsync/redsync/v4 v4.8.1 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/go-stack/stack v1.8.0 // indirect + github.com/gofiber/fiber/v2 v2.52.4 // indirect github.com/gofiber/template v1.8.3 // indirect + github.com/gofiber/template/html/v2 v2.1.1 // indirect github.com/gofiber/utils v1.1.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect @@ -174,7 +174,7 @@ require ( google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect - google.golang.org/grpc v1.64.0 // indirect + google.golang.org/grpc v1.64.1 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/frameworks/Go/goravel/src/fiber/go.sum b/frameworks/Go/goravel/src/fiber/go.sum index 942ea9c3e7f..e036eea01cf 100644 --- a/frameworks/Go/goravel/src/fiber/go.sum +++ b/frameworks/Go/goravel/src/fiber/go.sum @@ -1096,8 +1096,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= +google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 14e4e09f660c92be1ca1fd557415950e7bbeaec7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 22:08:43 +0000 Subject: [PATCH 34/62] Bump mysql2 from 3.9.7 to 3.9.8 in /frameworks/JavaScript/sailsjs Bumps [mysql2](https://github.com/sidorares/node-mysql2) from 3.9.7 to 3.9.8. - [Release notes](https://github.com/sidorares/node-mysql2/releases) - [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md) - [Commits](https://github.com/sidorares/node-mysql2/compare/v3.9.7...v3.9.8) --- updated-dependencies: - dependency-name: mysql2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/JavaScript/sailsjs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/sailsjs/package.json b/frameworks/JavaScript/sailsjs/package.json index 9be38df56ad..b2886f07639 100644 --- a/frameworks/JavaScript/sailsjs/package.json +++ b/frameworks/JavaScript/sailsjs/package.json @@ -10,7 +10,7 @@ "ejs": "3.1.10", "handlebars": "4.7.6", "mysql": "2.16.0", - "mysql2": "3.9.7", + "mysql2": "3.9.8", "pg": "6.0.5", "pg-hstore": "2.3.2", "rc": "1.1.6", From 11376ea45ca3b9067b24690cc0acc5b7c9fe88cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 08:42:44 -0700 Subject: [PATCH 35/62] Bump mysql2 from 3.9.7 to 3.9.8 in /frameworks/JavaScript/nodejs (#9154) Bumps [mysql2](https://github.com/sidorares/node-mysql2) from 3.9.7 to 3.9.8. - [Release notes](https://github.com/sidorares/node-mysql2/releases) - [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md) - [Commits](https://github.com/sidorares/node-mysql2/compare/v3.9.7...v3.9.8) --- updated-dependencies: - dependency-name: mysql2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frameworks/JavaScript/nodejs/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/nodejs/package.json b/frameworks/JavaScript/nodejs/package.json index 8af5fedae2b..28dc35a011c 100644 --- a/frameworks/JavaScript/nodejs/package.json +++ b/frameworks/JavaScript/nodejs/package.json @@ -8,7 +8,7 @@ "mongodb": "3.7.3", "mongoose": "5.13.20", "mysql": "2.16.0", - "mysql2": "3.9.7", + "mysql2": "3.9.8", "parseurl": "1.3.2", "pg": "8.5.0", "pg-hstore": "2.3.2", From d54303b8cdcd145d074925573c9e914f1ab0fbf9 Mon Sep 17 00:00:00 2001 From: Giovanni Barillari Date: Thu, 11 Jul 2024 19:01:41 +0200 Subject: [PATCH 36/62] [Python] Bump Granian to 1.5.x (#9157) --- frameworks/Python/emmett/requirements.txt | 2 +- frameworks/Python/emmett/run.py | 7 ++++--- frameworks/Python/granian/requirements.txt | 2 +- frameworks/Python/granian/run.py | 13 +++++++++---- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/frameworks/Python/emmett/requirements.txt b/frameworks/Python/emmett/requirements.txt index 2c329705017..627a2187091 100644 --- a/frameworks/Python/emmett/requirements.txt +++ b/frameworks/Python/emmett/requirements.txt @@ -1,2 +1,2 @@ -emmett[orjson]>=2.5.3,<2.6.0 +emmett[orjson]>=2.5.12,<2.6.0 psycopg2-binary==2.9.5 diff --git a/frameworks/Python/emmett/run.py b/frameworks/Python/emmett/run.py index 42679101ea0..02a21e458f9 100644 --- a/frameworks/Python/emmett/run.py +++ b/frameworks/Python/emmett/run.py @@ -4,16 +4,17 @@ if __name__ == "__main__": - cpus = multiprocessing.cpu_count() + workers = round(multiprocessing.cpu_count() / 2) run( "rsgi", ("app", "app"), host="0.0.0.0", port=8080, - workers=cpus, + workers=workers, backlog=16384, - threading_mode='runtime', + threading_mode="runtime", + http="1", enable_websockets=False, log_level="warn" ) diff --git a/frameworks/Python/granian/requirements.txt b/frameworks/Python/granian/requirements.txt index e1b7c479119..1a22a3ddfc2 100644 --- a/frameworks/Python/granian/requirements.txt +++ b/frameworks/Python/granian/requirements.txt @@ -1,4 +1,4 @@ asyncpg==0.29.0 -granian>=1.4.2,<1.5.0 +granian>=1.5.1,<1.6.0 jinja2==3.1.4 orjson==3.10.2 diff --git a/frameworks/Python/granian/run.py b/frameworks/Python/granian/run.py index acdad59a542..910b248422b 100644 --- a/frameworks/Python/granian/run.py +++ b/frameworks/Python/granian/run.py @@ -7,9 +7,14 @@ if __name__ == '__main__': interface = sys.argv[1] threading_mode = sys.argv[2] - workers = multiprocessing.cpu_count() - if threading_mode == "workers": - workers = round(workers / 2) + + #: split cores between the two loops + workers = round(multiprocessing.cpu_count() / 2) + + blocking_threads = None + if interface == "wsgi": + #: we don't run any I/O in WSGI benches + blocking_threads = 1 Granian( f"app_{interface}:main", @@ -17,7 +22,7 @@ port=8080, workers=workers, threading_mode=threading_mode, - blocking_threads=1, + blocking_threads=blocking_threads, backlog=16384, interface=interface, http="1", From 0ef534b6fce72f197333d70a3f60362e798bb8e7 Mon Sep 17 00:00:00 2001 From: uNetworkingAB <110806833+uNetworkingAB@users.noreply.github.com> Date: Thu, 11 Jul 2024 19:04:23 +0200 Subject: [PATCH 37/62] Gnet is unrealistic (#9159) * [gnet] is unrealistic * Update benchmark_config.json --- frameworks/Go/gnet/benchmark_config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frameworks/Go/gnet/benchmark_config.json b/frameworks/Go/gnet/benchmark_config.json index 484ec41b8ff..3999bd74f97 100644 --- a/frameworks/Go/gnet/benchmark_config.json +++ b/frameworks/Go/gnet/benchmark_config.json @@ -4,8 +4,8 @@ "default": { "plaintext_url": "/plaintext", "port": 8080, - "approach": "Realistic", - "classification": "Platform", + "approach": "stripped", + "classification": "Micro", "database": "None", "framework": "gnet", "language": "Go", @@ -20,4 +20,4 @@ "versus": "go" } }] -} \ No newline at end of file +} From 4b0a91f07147386c8f11b36b1410f00b34c7611c Mon Sep 17 00:00:00 2001 From: Nate Date: Thu, 11 Jul 2024 10:22:13 -0700 Subject: [PATCH 38/62] Remove uwebsockets (#9160) --- .../JavaScript/uwebsockets.js/README.md | 55 ----- .../uwebsockets.js/benchmark_config.json | 68 ------ .../uwebsockets.js/package-lock.json | 105 ---------- .../JavaScript/uwebsockets.js/package.json | 18 -- .../uwebsockets.js/src/clustered.js | 23 --- .../uwebsockets.js/src/database/mysql.js | 16 -- .../uwebsockets.js/src/database/postgres.js | 17 -- .../JavaScript/uwebsockets.js/src/server.js | 194 ------------------ .../JavaScript/uwebsockets.js/src/utils.js | 86 -------- .../uwebsockets.js-mysql.dockerfile | 12 -- .../uwebsockets.js-postgres.dockerfile | 12 -- .../uwebsockets.js/uwebsockets.js.dockerfile | 11 - 12 files changed, 617 deletions(-) delete mode 100644 frameworks/JavaScript/uwebsockets.js/README.md delete mode 100644 frameworks/JavaScript/uwebsockets.js/benchmark_config.json delete mode 100644 frameworks/JavaScript/uwebsockets.js/package-lock.json delete mode 100644 frameworks/JavaScript/uwebsockets.js/package.json delete mode 100644 frameworks/JavaScript/uwebsockets.js/src/clustered.js delete mode 100644 frameworks/JavaScript/uwebsockets.js/src/database/mysql.js delete mode 100644 frameworks/JavaScript/uwebsockets.js/src/database/postgres.js delete mode 100644 frameworks/JavaScript/uwebsockets.js/src/server.js delete mode 100644 frameworks/JavaScript/uwebsockets.js/src/utils.js delete mode 100644 frameworks/JavaScript/uwebsockets.js/uwebsockets.js-mysql.dockerfile delete mode 100644 frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile delete mode 100644 frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile diff --git a/frameworks/JavaScript/uwebsockets.js/README.md b/frameworks/JavaScript/uwebsockets.js/README.md deleted file mode 100644 index 73fc530d673..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# uWebSockets.js Benchmarking Test - -uWebSockets is a web server written in C/C++ (https://github.com/uNetworking/uWebSockets) - -µWebSockets.js is a web server bypass for Node.js (https://github.com/uNetworking/uWebSockets.js) - -## Important Libraries - -The tests were run with: - -- [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js/) -- [postgres](https://github.com/porsager/postgres/) -- [mariadb](https://github.com/mariadb-corporation/mariadb-connector-nodejs/) - -## Database - -There are individual handlers for each DB approach. The logic for each of them are found here: - -- [PostgreSQL](src/database/postgres.js) -- [MySQL](src/database/mysql.js) - -There are **no database endpoints** or drivers attached by default. - -To initialize the application with one of these, run any _one_ of the following commands: - -```sh -$ DATABASE=postgres npm start -$ DATABASE=mysql npm start -``` - -## Test Endpoints - -> Visit the test requirements [here](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview) - -```sh -$ curl localhost:8080/json -$ curl localhost:8080/plaintext - -# The following are only available with the DATABASE env var - -$ curl localhost:8080/db -$ curl localhost:8080/fortunes - -$ curl localhost:8080/updates?queries= -$ curl localhost:8080/updates?queries=2 -$ curl localhost:8080/updates?queries=1000 -$ curl localhost:8080/updates?queries=foo -$ curl localhost:8080/updates?queries=0 - -$ curl localhost:8080/queries?queries= -$ curl localhost:8080/queries?queries=2 -$ curl localhost:8080/queries?queries=1000 -$ curl localhost:8080/queries?queries=foo -$ curl localhost:8080/queries?queries=0 -``` diff --git a/frameworks/JavaScript/uwebsockets.js/benchmark_config.json b/frameworks/JavaScript/uwebsockets.js/benchmark_config.json deleted file mode 100644 index fee055f341a..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/benchmark_config.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "framework": "uwebsockets.js", - "tests": [ - { - "default": { - "approach": "Realistic", - "classification": "Platform", - "database": "None", - "database_os": "Linux", - "display_name": "uWebSockets.js", - "flavor": "NodeJS", - "framework": "uWebSockets.js", - "json_url": "/json", - "language": "JavaScript", - "notes": "", - "orm": "Raw", - "os": "Linux", - "plaintext_url": "/plaintext", - "platform": "nodejs", - "port": 8080, - "versus": "nodejs", - "webserver": "None" - }, - "postgres": { - "approach": "Realistic", - "classification": "Platform", - "database": "Postgres", - "database_os": "Linux", - "db_url": "/db", - "display_name": "uWebSockets.js", - "flavor": "NodeJS", - "fortune_url": "/fortunes", - "framework": "uWebSockets.js", - "language": "JavaScript", - "notes": "", - "orm": "Raw", - "os": "Linux", - "platform": "None", - "port": 8080, - "query_url": "/queries?queries=", - "update_url": "/updates?queries=", - "versus": "nodejs", - "webserver": "None" - }, - "mysql": { - "approach": "Realistic", - "classification": "Platform", - "database": "MySQL", - "database_os": "Linux", - "db_url": "/db", - "display_name": "uWebSockets.js", - "flavor": "NodeJS", - "fortune_url": "/fortunes", - "framework": "uWebSockets.js", - "language": "JavaScript", - "notes": "", - "orm": "Raw", - "os": "Linux", - "platform": "None", - "port": 8080, - "query_url": "/queries?queries=", - "update_url": "/updates?queries=", - "versus": "nodejs", - "webserver": "None" - } - } - ] -} diff --git a/frameworks/JavaScript/uwebsockets.js/package-lock.json b/frameworks/JavaScript/uwebsockets.js/package-lock.json deleted file mode 100644 index 910703e95b8..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/package-lock.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "name": "uwebsockets.js", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "uwebsockets.js", - "version": "0.0.1", - "license": "MIT", - "dependencies": { - "mariadb": "^3.3.0", - "postgres": "^3.4.4", - "slow-json-stringify": "^2.0.1", - "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" - } - }, - "node_modules/@types/geojson": { - "version": "7946.0.14", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", - "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" - }, - "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", - "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/mariadb": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/mariadb/-/mariadb-3.3.0.tgz", - "integrity": "sha512-sAL4bJgbfCAtXcE8bXI+NAMzVaPNkIU8hRZUXYfgNFoWB9U57G3XQiMeCx/A6IrS6y7kGwBLylrwgsZQ8kUYlw==", - "dependencies": { - "@types/geojson": "^7946.0.14", - "@types/node": "^20.11.17", - "denque": "^2.1.0", - "iconv-lite": "^0.6.3", - "lru-cache": "^10.2.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/postgres": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.4.tgz", - "integrity": "sha512-IbyN+9KslkqcXa8AO9fxpk97PA4pzewvpi2B3Dwy9u4zpV32QicaEdgmF3eSQUzdRk7ttDHQejNgAEr4XoeH4A==", - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/porsager" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/slow-json-stringify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/slow-json-stringify/-/slow-json-stringify-2.0.1.tgz", - "integrity": "sha512-jqyzIqTaSkRGcWdWqjmOLKHZgOGUT71ZCTsvQu1xGu9Mqaod7O26y5FJJEmaUQhaTWh0bkXv2qqN0i+EQsD1jQ==" - }, - "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" - }, - "node_modules/uWebSockets.js": { - "version": "20.44.0", - "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#8fa05571bf6ea95be8966ad313d9d39453e381ae" - } - } -} diff --git a/frameworks/JavaScript/uwebsockets.js/package.json b/frameworks/JavaScript/uwebsockets.js/package.json deleted file mode 100644 index ec5bc0c1d73..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "dependencies": { - "mariadb": "^3.3.0", - "postgres": "^3.4.4", - "slow-json-stringify": "^2.0.1", - "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" - }, - "license": "MIT", - "main": "src/server.js", - "name": "uwebsockets.js", - "private": true, - "scripts": { - "dev": "node src/server.js", - "start": "node src/clustered.js" - }, - "type": "module", - "version": "0.0.1" -} diff --git a/frameworks/JavaScript/uwebsockets.js/src/clustered.js b/frameworks/JavaScript/uwebsockets.js/src/clustered.js deleted file mode 100644 index 95a57ec77f3..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/src/clustered.js +++ /dev/null @@ -1,23 +0,0 @@ -import cluster from "node:cluster"; -import os from "node:os"; -import process from "node:process"; - -if (cluster.isPrimary) { - // Master Node - console.log(`Primary ${process.pid} is running`); - - // Fork workers - const numCPUs = os.availableParallelism(); - for (let i = 0; i < numCPUs; i++) { - cluster.fork(); - } - - cluster.on("exit", (worker) => { - console.log(`worker ${worker.process.pid} died`); - process.exit(1); - }); -} else { - // Cluster Node - await import("./server.js"); - console.log(`Worker ${process.pid} started`); -} diff --git a/frameworks/JavaScript/uwebsockets.js/src/database/mysql.js b/frameworks/JavaScript/uwebsockets.js/src/database/mysql.js deleted file mode 100644 index a627a74d132..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/src/database/mysql.js +++ /dev/null @@ -1,16 +0,0 @@ -import { createPool } from "mariadb"; -import os from "node:os"; - -const pool = createPool({ - host: "tfb-database", - user: "benchmarkdbuser", - password: "benchmarkdbpass", - database: "hello_world", - connectionLimit: os.availableParallelism() -}); - -export const fortunes = async () => await pool.execute("SELECT id, message FROM fortune"); - -export const find = async (id) => await pool.execute("SELECT id, randomnumber FROM world WHERE id = ?", [id]).then((arr) => arr[0]); - -export const bulkUpdate = async (worlds) => await Promise.all(worlds.map(world => pool.execute("UPDATE world SET randomnumber = ? WHERE id = ?", [world.randomNumber, world.id]))); diff --git a/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js b/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js deleted file mode 100644 index 105eeef99e5..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js +++ /dev/null @@ -1,17 +0,0 @@ -import postgres from "postgres"; - -const sql = postgres({ - host: "tfb-database", - user: "benchmarkdbuser", - password: "benchmarkdbpass", - database: "hello_world", - max: 1 -}); - -export const fortunes = async () => await sql`SELECT id, message FROM fortune`; - -export const find = async (id) => await sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then((arr) => arr[0]); - -export const bulkUpdate = async (worlds) => await sql`UPDATE world SET randomNumber = (update_data.randomNumber)::int - FROM (VALUES ${sql(worlds.map(world => [world.id, world.randomNumber]).sort((a, b) => (a[0] < b[0]) ? -1 : 1))}) AS update_data (id, randomNumber) - WHERE world.id = (update_data.id)::int`; diff --git a/frameworks/JavaScript/uwebsockets.js/src/server.js b/frameworks/JavaScript/uwebsockets.js/src/server.js deleted file mode 100644 index 1db7d391f2a..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/src/server.js +++ /dev/null @@ -1,194 +0,0 @@ -import uWebSockets from "uWebSockets.js"; -import { - addBenchmarkHeaders, - generateRandomNumber, - getQueriesCount, - handleError, - escape, - jsonSerializer, - worldObjectSerializer, - sortByMessage -} from "./utils.js"; - -let db; -const { DATABASE } = process.env; -if (DATABASE) db = await import(`./database/${DATABASE}.js`); - -const webserver = uWebSockets.App(); - -webserver.get("/plaintext", new uWebSockets.DeclarativeResponse() - .writeHeader("Server", "uWebSockets.js") - .writeHeader("Content-Type", "text/plain") - .end("Hello, World!") -); - -webserver.get("/json", (response) => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "application/json"); - // response.end(JSON.stringify({ message: "Hello, World!" })); - response.end(jsonSerializer({ message: "Hello, World!" })); -}); - -if (db) { - webserver.get("/db", async (response) => { - response.onAborted(() => { - response.aborted = true; - }); - - try { - const row = await db.find(generateRandomNumber()); - - if (response.aborted) { - return; - } - - response.cork(() => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "application/json"); - // response.end(JSON.stringify(rows)); - response.end(worldObjectSerializer(row)); - }); - } catch (error) { - if (response.aborted) { - return; - } - - handleError(error, response); - } - }); - - webserver.get("/queries", async (response, request) => { - response.onAborted(() => { - response.aborted = true; - }); - - try { - const queriesCount = getQueriesCount(request); - - const databaseJobs = new Array(queriesCount); - - for (let i = 0; i < queriesCount; i++) { - databaseJobs[i] = db.find(generateRandomNumber()); - } - - const worldObjects = await Promise.all(databaseJobs); - - if (response.aborted) { - return; - } - - response.cork(() => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "application/json"); - response.end(JSON.stringify(worldObjects)); - }); - } catch (error) { - if (response.aborted) { - return; - } - - handleError(error, response); - } - }); - - const extra = { id: 0, message: "Additional fortune added at request time." }; - - webserver.get("/fortunes", async (response) => { - response.onAborted(() => { - response.aborted = true; - }); - - try { - const rows = [extra, ...await db.fortunes()]; - - if (response.aborted) { - return; - } - - // rows.push({ - // id: 0, - // message: "Additional fortune added at request time.", - // }); - - // rows.sort((a, b) => (a.message < b.message) ? -1 : 1); - sortByMessage(rows) - - const n = rows.length - - let html = "", i = 0; - for (; i < n; i++) { - html += `${rows[i].id}${escape(rows[i].message)}`; - } - - response.cork(() => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "text/html; charset=utf-8"); - response.end(`Fortunes${html}
idmessage
`); - }); - } catch (error) { - if (response.aborted) { - return; - } - - handleError(error, response); - } - }); - - webserver.get("/updates", async (response, request) => { - response.onAborted(() => { - response.aborted = true; - }); - - try { - const queriesCount = getQueriesCount(request); - - const databaseJobs = new Array(queriesCount); - - for (let i = 0; i < queriesCount; i++) { - databaseJobs[i] = db.find(generateRandomNumber()); - } - - const worldObjects = await Promise.all(databaseJobs); - - for (let i = 0; i < queriesCount; i++) { - worldObjects[i].randomNumber = generateRandomNumber(); - } - - await db.bulkUpdate(worldObjects); - - if (response.aborted) { - return; - } - - response.cork(() => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "application/json"); - response.end(JSON.stringify(worldObjects)); - }); - } catch (error) { - if (response.aborted) { - return; - } - - handleError(error, response); - } - }); -} - -webserver.any("/*", (response) => { - response.writeStatus("404 Not Found"); - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "text/plain"); - response.end("Not Found"); -}); - -const host = process.env.HOST || "0.0.0.0"; -const port = parseInt(process.env.PORT || "8080"); -webserver.listen(host, port, (socket) => { - if (!socket) { - console.error(`Couldn't bind to http://${host}:${port}!`); - process.exit(1); - } - - console.log(`Successfully bound to http://${host}:${port}.`); -}); diff --git a/frameworks/JavaScript/uwebsockets.js/src/utils.js b/frameworks/JavaScript/uwebsockets.js/src/utils.js deleted file mode 100644 index b3d46e7e11c..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/src/utils.js +++ /dev/null @@ -1,86 +0,0 @@ -import { sjs, attr } from 'slow-json-stringify' - -/** - * Add Benchmark HTTP response headers. - * - * Add HTTP response headers `Server` which is required by the test suite. - * Header `Date` is automatically added by uWebsockets - * https://github.com/uNetworking/uWebSockets/blob/master/src/HttpResponse.h#L78 - * - * https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview - * - * @param {import('uWebSockets.js').HttpResponse} response - */ -export function addBenchmarkHeaders(response) { - response.writeHeader("Server", "uWebSockets.js"); -} - -/** - * Handle error for response - * - * @param {Error} error - * @param {import('uWebSockets.js').HttpResponse} response - */ -export function handleError(error, response) { - console.error(error); - response.cork(() => { - addBenchmarkHeaders(response); - response.writeHeader("Content-Type", "text/plain"); - response.end("Internal Server Error"); - }); -} - -/** - * Get queries count - * - * @param {import('uWebSockets.js').HttpRequest} request - */ -export function getQueriesCount(request) { - return Math.min(parseInt(request.getQuery("queries")) || 1, 500); -} - -/** - * Generate random number - * - */ -export function generateRandomNumber() { - return Math.ceil(Math.random() * 10000); -} - -/** - * Escape unsafe HTML Code - * - */ -const escapeHTMLRules = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' } - -const unsafeHTMLMatcher = /[&<>"'\/]/g - -export function escape(text) { - if (unsafeHTMLMatcher.test(text) === false) return text; - return text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; }); -} - -/** - * Using Slow json stringify module to get faster results - */ -export const jsonSerializer = sjs({ message: attr("string")}); -export const worldObjectSerializer = sjs({ id: attr('number'), randomnumber: attr('number') }); -// export const worldObjectsSerializer = sjs({ rows: attr("array", worldObjectSerializer) }); - -/** - * Using Sort method which is performant for the test scenario - * @returns - */ -export function sortByMessage (arr) { - const n = arr.length - for (let i = 1; i < n; i++) { - const c = arr[i] - let j = i - 1 - while ((j > -1) && (c.message < arr[j].message)) { - arr[j + 1] = arr[j] - j-- - } - arr[j + 1] = c - } - return arr -} \ No newline at end of file diff --git a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-mysql.dockerfile b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-mysql.dockerfile deleted file mode 100644 index 8533d8b9a61..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-mysql.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:20-slim - -COPY ./ ./ - -RUN npm install - -ENV NODE_ENV production -ENV DATABASE mysql - -EXPOSE 8080 - -CMD ["npm", "start"] diff --git a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile deleted file mode 100644 index ba7d0eee5f6..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -FROM node:20-slim - -COPY ./ ./ - -RUN npm install - -ENV NODE_ENV production -ENV DATABASE postgres - -EXPOSE 8080 - -CMD ["npm", "start"] diff --git a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile deleted file mode 100644 index 4262ad19953..00000000000 --- a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -FROM node:20-slim - -COPY ./ ./ - -RUN npm install - -ENV NODE_ENV production - -EXPOSE 8080 - -CMD ["npm", "start"] From 4022ec349164c56929c47d283302ad531cac3d26 Mon Sep 17 00:00:00 2001 From: Nate Date: Thu, 11 Jul 2024 10:47:19 -0700 Subject: [PATCH 39/62] Code of conduct (#9161) --- CODE_OF_CONDUCT.md | 133 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..38838d563cc --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +tfb@techempower.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations From 562e515c5ce3b956861cd089dd5ac3e9d8e61622 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 21:01:40 +0000 Subject: [PATCH 40/62] Bump org.apache.wicket:wicket-core in /frameworks/Java/wicket Bumps org.apache.wicket:wicket-core from 9.6.0 to 9.18.0. --- updated-dependencies: - dependency-name: org.apache.wicket:wicket-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Java/wicket/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Java/wicket/pom.xml b/frameworks/Java/wicket/pom.xml index ec30df52f27..c0f0303051d 100644 --- a/frameworks/Java/wicket/pom.xml +++ b/frameworks/Java/wicket/pom.xml @@ -24,7 +24,7 @@ 11 2.13.0 1.7.25 - 9.6.0 + 9.18.0 From d2c0d69d7ba404a04f24808f86a1c6f46ad5720c Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Tue, 16 Jul 2024 17:48:06 +0200 Subject: [PATCH 41/62] [rails] Enable YJIT after boot (#9163) There is no need to run the JIT on code that is only used during boot. This is also the new default in newer Rails applications. --- .../Ruby/rails/config/initializers/enable_yjit.rb | 11 +++++++++++ frameworks/Ruby/rails/rails-mysql.dockerfile | 2 +- frameworks/Ruby/rails/rails.dockerfile | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 frameworks/Ruby/rails/config/initializers/enable_yjit.rb diff --git a/frameworks/Ruby/rails/config/initializers/enable_yjit.rb b/frameworks/Ruby/rails/config/initializers/enable_yjit.rb new file mode 100644 index 00000000000..963858ab4c6 --- /dev/null +++ b/frameworks/Ruby/rails/config/initializers/enable_yjit.rb @@ -0,0 +1,11 @@ +# Automatically enable YJIT as of Ruby 3.3, as it bring very +# sizeable performance improvements. + +# If you are deploying to a memory constrained environment +# you may want to delete this file, but otherwise it's free +# performance. +if defined? RubyVM::YJIT.enable + Rails.application.config.after_initialize do + RubyVM::YJIT.enable + end +end diff --git a/frameworks/Ruby/rails/rails-mysql.dockerfile b/frameworks/Ruby/rails/rails-mysql.dockerfile index ae512cbdafd..b14a3b75af6 100644 --- a/frameworks/Ruby/rails/rails-mysql.dockerfile +++ b/frameworks/Ruby/rails/rails-mysql.dockerfile @@ -5,7 +5,7 @@ RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-se EXPOSE 8080 WORKDIR /rails -ENV RUBY_YJIT_ENABLE=1 +# ENV RUBY_YJIT_ENABLE=1 YJIT is enabled in config/initializers/enable_yjit.rb # Use Jemalloc RUN apt-get update && \ diff --git a/frameworks/Ruby/rails/rails.dockerfile b/frameworks/Ruby/rails/rails.dockerfile index 99c16e935bb..392920be9c4 100644 --- a/frameworks/Ruby/rails/rails.dockerfile +++ b/frameworks/Ruby/rails/rails.dockerfile @@ -5,7 +5,8 @@ RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-se EXPOSE 8080 WORKDIR /rails -ENV RUBY_YJIT_ENABLE=1 +# ENV RUBY_YJIT_ENABLE=1 YJIT is enabled in config/initializers/enable_yjit.rb + # Use Jemalloc RUN apt-get update && \ apt-get install -y --no-install-recommends libjemalloc2 From 93918507a4b9ce2d35f4e40596acde022dda8498 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Tue, 16 Jul 2024 17:48:42 +0200 Subject: [PATCH 42/62] [ruby/roda] Use rapidjson for faster JSON serialization (#9164) --- frameworks/Ruby/roda-sequel/Gemfile | 2 +- frameworks/Ruby/roda-sequel/boot.rb | 5 +---- frameworks/Ruby/roda-sequel/hello_world.rb | 8 ++++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/frameworks/Ruby/roda-sequel/Gemfile b/frameworks/Ruby/roda-sequel/Gemfile index c9c6a48ab89..e511bb3d848 100644 --- a/frameworks/Ruby/roda-sequel/Gemfile +++ b/frameworks/Ruby/roda-sequel/Gemfile @@ -7,7 +7,7 @@ gem "sequel", "~> 5.67" gem "roda", "~> 3.66" gem "tilt", "~> 2.1", require: "tilt/erb" gem "unicorn", "~> 6.1", platforms: %i[ruby mswin], require: false -gem "oj", "~> 3.14" +gem "rapidjson" group :mysql do gem "mysql2", "~> 0.5", platforms: %i[ruby mswin] diff --git a/frameworks/Ruby/roda-sequel/boot.rb b/frameworks/Ruby/roda-sequel/boot.rb index ebeb5a584c4..bc7277e2362 100644 --- a/frameworks/Ruby/roda-sequel/boot.rb +++ b/frameworks/Ruby/roda-sequel/boot.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "bundler/setup" require "time" -require "oj" +require "rapidjson" MAX_PK = 10_000 QUERY_RANGE = (1..MAX_PK).freeze ALL_IDS = QUERY_RANGE.to_a @@ -9,9 +9,6 @@ QUERIES_MAX = 500 SEQUEL_NO_ASSOCIATIONS = true -# Use the OJ gem instead of the JSON one -Oj.mimic_JSON() - SERVER_STRING = if defined?(PhusionPassenger) [ diff --git a/frameworks/Ruby/roda-sequel/hello_world.rb b/frameworks/Ruby/roda-sequel/hello_world.rb index 6a0a43efccb..458e1a7c687 100644 --- a/frameworks/Ruby/roda-sequel/hello_world.rb +++ b/frameworks/Ruby/roda-sequel/hello_world.rb @@ -22,13 +22,13 @@ def rand1 # Test type 1: JSON serialization r.is "json" do response[CONTENT_TYPE] = JSON_TYPE - { message: "Hello, World!" }.to_json + RapidJSON.encode({ message: "Hello, World!" }) end # Test type 2: Single database query r.is "db" do response[CONTENT_TYPE] = JSON_TYPE - World.with_pk(rand1).values.to_json + RapidJSON.encode(World.with_pk(rand1).values) end # Test type 3: Multiple database queries @@ -40,7 +40,7 @@ def rand1 World.with_pk(id).values end end - worlds.to_json + RapidJSON.encode(worlds) end # Test type 4: Fortunes @@ -70,7 +70,7 @@ def rand1 end World.batch_update(worlds) end - worlds.map(&:values).to_json + RapidJSON.encode(worlds.map!(&:values)) end # Test type 6: Plaintext From e1dcb73c829d2a7b76d45a436522a4fec3489fde Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Tue, 16 Jul 2024 17:48:59 +0200 Subject: [PATCH 43/62] [ruby/rack] Enable Rubys M:N thread scheduler for Puma (#8678) With the M:N thread scheduler thread creation and management cost are reduced. --- frameworks/Ruby/rack/rack.dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/frameworks/Ruby/rack/rack.dockerfile b/frameworks/Ruby/rack/rack.dockerfile index e40bfced37a..b9b39c43122 100644 --- a/frameworks/Ruby/rack/rack.dockerfile +++ b/frameworks/Ruby/rack/rack.dockerfile @@ -1,6 +1,7 @@ FROM ruby:3.4-rc ENV RUBY_YJIT_ENABLE=1 +ENV RUBY_MN_THREADS=1 # Use Jemalloc RUN apt-get update && \ From 527c38d3dcc3967feca67a93730b1d0780c43e8a Mon Sep 17 00:00:00 2001 From: Edgar Espina Date: Tue, 16 Jul 2024 11:49:14 -0400 Subject: [PATCH 44/62] jooby: upgrade 3.2.4 (#9156) - get back threadlocal buffer for fortunes - implements vertx like sql updates --- frameworks/Java/jooby/pom.xml | 4 +- .../src/main/java/com/techempower/App.java | 9 +-- .../main/java/com/techempower/PgClient.java | 75 +++++++++++++++---- .../main/java/com/techempower/ReactivePg.java | 18 +---- .../rocker/BufferRockerOutput.java | 65 ++++++++++++++++ 5 files changed, 134 insertions(+), 37 deletions(-) create mode 100644 frameworks/Java/jooby/src/main/java/com/techempower/rocker/BufferRockerOutput.java diff --git a/frameworks/Java/jooby/pom.xml b/frameworks/Java/jooby/pom.xml index 338f8ca065d..bd6ce1a1c68 100644 --- a/frameworks/Java/jooby/pom.xml +++ b/frameworks/Java/jooby/pom.xml @@ -11,8 +11,8 @@ jooby - 3.1.2 - 4.1.110.Final + 3.2.4 + 4.1.111.Final 2.0.2 42.7.3 UTF-8 diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/App.java b/frameworks/Java/jooby/src/main/java/com/techempower/App.java index f7cf3373b4a..7a75f05d60b 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/App.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/App.java @@ -28,13 +28,8 @@ public class App extends Jooby { private static final byte[] MESSAGE_BYTES = MESSAGE.getBytes(StandardCharsets.US_ASCII); - private static final ByteBuffer MESSAGE_BUFFER = (ByteBuffer) ByteBuffer - .allocateDirect(MESSAGE_BYTES.length) - .put(MESSAGE_BYTES) - .flip(); - { - + var bufferFactory = getBufferFactory(); /** Database: */ install(new HikariModule()); DataSource ds = require(DataSource.class); @@ -43,7 +38,7 @@ public class App extends Jooby { install(new RockerModule()); get("/plaintext", ctx -> - ctx.send(MESSAGE_BUFFER.duplicate()) + ctx.send(bufferFactory.wrap(MESSAGE_BYTES)) ); get("/json", ctx -> ctx diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/PgClient.java b/frameworks/Java/jooby/src/main/java/com/techempower/PgClient.java index 4847ddab1de..dd5e9197f01 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/PgClient.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/PgClient.java @@ -1,5 +1,7 @@ package com.techempower; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; import java.util.function.BiConsumer; @@ -32,10 +34,13 @@ public class PgClient { private static final String SELECT_FORTUNE = "SELECT id, message from FORTUNE"; private static class DbConnection { + private SqlClientInternal queries; private PreparedQuery> SELECT_WORLD_QUERY; private PreparedQuery> SELECT_FORTUNE_QUERY; private PreparedQuery> UPDATE_WORLD_QUERY; - private SqlClientInternal connection; + private SqlClientInternal updates; + @SuppressWarnings("unchecked") + private PreparedQuery>[] AGGREGATED_UPDATE_WORLD_QUERY = new PreparedQuery[128]; } private static class DbConnectionFactory extends ThreadLocal { @@ -64,20 +69,32 @@ private Handler> onSuccess(Handler handler) { .setWorkerPoolSize(1) .setInternalBlockingPoolSize(1) ); - var future = PgConnection.connect(vertx, options) + var client1 = PgConnection.connect(vertx, options) .flatMap(conn -> { - result.connection = (SqlClientInternal) conn; + result.queries = (SqlClientInternal) conn; Future f1 = conn.prepare(SELECT_WORLD) .andThen(onSuccess(ps -> result.SELECT_WORLD_QUERY = ps.query())); Future f2 = conn.prepare(SELECT_FORTUNE) .andThen(onSuccess(ps -> result.SELECT_FORTUNE_QUERY = ps.query())); - Future f3 = conn.prepare(UPDATE_WORLD) - .andThen(onSuccess(ps -> result.UPDATE_WORLD_QUERY = ps.query())); - return Future.join(f1, f2, f3); - }) - .toCompletionStage() - .toCompletableFuture() - .get(); + return Future.join(f1, f2); + }); + + var client2 = PgConnection.connect(vertx, options) + .flatMap(conn -> { + result.updates = (SqlClientInternal) conn; + List> list = new ArrayList<>(); + Future f1 = conn.prepare(UPDATE_WORLD) + .andThen(onSuccess(ps -> result.UPDATE_WORLD_QUERY = ps.query())); + list.add(f1); + for (int i = 0; i < result.AGGREGATED_UPDATE_WORLD_QUERY.length; i++) { + int idx = i; + list.add(conn + .prepare(buildAggregatedUpdateQuery(1 + idx)) + .andThen(onSuccess(ps -> result.AGGREGATED_UPDATE_WORLD_QUERY[idx] = ps.query()))); + } + return Future.join(list); + }); + var future = Future.join(client1, client2).toCompletionStage().toCompletableFuture().get(); Throwable cause = future.cause(); if (cause != null) { @@ -91,6 +108,18 @@ private Handler> onSuccess(Handler handler) { throw SneakyThrows.propagate(ex.getCause()); } } + + private static String buildAggregatedUpdateQuery(int len) { + StringBuilder sb = new StringBuilder(); + sb.append("UPDATE world SET randomNumber = update_data.randomNumber FROM (VALUES"); + char sep = ' '; + for (int i = 1;i <= len;i++) { + sb.append(sep).append("($").append(2 * i - 1).append("::int,$").append(2 * i).append("::int)"); + sep = ','; + } + sb.append(") AS update_data (id, randomNumber) WHERE world.id = update_data.id"); + return sb.toString(); + } } private final ThreadLocal sqlClient; @@ -104,7 +133,7 @@ public void selectWorld(Tuple row, Handler>> handler) { } public void selectWorlds(int queries, Handler>> handler) { - this.sqlClient.get().connection.group(c -> { + this.sqlClient.get().queries.group(c -> { for (int i = 0; i < queries; i++) { c.preparedQuery(SELECT_WORLD).execute(Tuple.of(Util.randomWorld()), handler); } @@ -117,7 +146,7 @@ public void fortunes(Handler>> handler) { public void selectWorldForUpdate(int queries, BiConsumer>> consumer) { - this.sqlClient.get().connection.group(c -> { + this.sqlClient.get().queries.group(c -> { PreparedQuery> statement = c.preparedQuery(SELECT_WORLD); for (int i = 0; i < queries; i++) { consumer.accept(i, statement); @@ -125,8 +154,26 @@ public void selectWorldForUpdate(int queries, }); } - public void updateWorld(List batch, Handler>> handler) { - this.sqlClient.get().UPDATE_WORLD_QUERY.executeBatch(batch, handler); + public void updateWorld(World[] worlds, Handler>> handler) { + Arrays.sort(worlds); + int len = worlds.length; + var connection = this.sqlClient.get(); + if (0 < len && len <= connection.AGGREGATED_UPDATE_WORLD_QUERY.length) { + List arguments = new ArrayList<>(); + for (World world : worlds) { + arguments.add(world.getId()); + arguments.add(world.getRandomNumber()); + } + Tuple tuple = Tuple.tuple(arguments); + PreparedQuery> query = connection.AGGREGATED_UPDATE_WORLD_QUERY[len - 1]; + query.execute(tuple, handler); + } else { + List batch = new ArrayList<>(); + for (World world : worlds) { + batch.add(Tuple.of(world.getRandomNumber(), world.getId())); + } + connection.UPDATE_WORLD_QUERY.executeBatch(batch, handler); + } } private PgConnectOptions pgPoolOptions(Config config) { diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java b/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java index 6a674c5e8df..c0eef6fb05a 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/ReactivePg.java @@ -7,10 +7,8 @@ import java.util.*; import com.fizzed.rocker.RockerOutputFactory; -import io.jooby.Context; -import io.jooby.Jooby; -import io.jooby.MediaType; -import io.jooby.ServerOptions; +import com.techempower.rocker.BufferRockerOutput; +import io.jooby.*; import io.jooby.rocker.DataBufferOutput; import io.jooby.rocker.RockerModule; import io.vertx.sqlclient.Row; @@ -18,7 +16,6 @@ import io.vertx.sqlclient.Tuple; public class ReactivePg extends Jooby { - { /** Reduce the number of resources due we do reactive processing. */ setServerOptions( @@ -84,14 +81,7 @@ public class ReactivePg extends Jooby { selectCallback.result().iterator().next().getInteger(0), randomWorld()); if (index == queries - 1) { - // Sort results... avoid dead locks - Arrays.sort(result); - List batch = new ArrayList<>(queries); - for (World world : result) { - batch.add(Tuple.of(world.getRandomNumber(), world.getId())); - } - - client.updateWorld(batch, updateCallback -> { + client.updateWorld(result, updateCallback -> { if (updateCallback.failed()) { sendError(ctx, updateCallback.cause()); } else { @@ -106,7 +96,7 @@ public class ReactivePg extends Jooby { }).setNonBlocking(true); /** Fortunes: */ - RockerOutputFactory factory = require(RockerOutputFactory.class); + var factory = BufferRockerOutput.factory(); get("/fortunes", ctx -> { client.fortunes(rsp -> { if (rsp.succeeded()) { diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/rocker/BufferRockerOutput.java b/frameworks/Java/jooby/src/main/java/com/techempower/rocker/BufferRockerOutput.java new file mode 100644 index 00000000000..78abf2056e4 --- /dev/null +++ b/frameworks/Java/jooby/src/main/java/com/techempower/rocker/BufferRockerOutput.java @@ -0,0 +1,65 @@ +package com.techempower.rocker; + +import com.fizzed.rocker.ContentType; +import com.fizzed.rocker.RockerOutput; +import com.fizzed.rocker.RockerOutputFactory; + +import java.io.IOException; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + +public class BufferRockerOutput implements RockerOutput { + private final ByteBuffer buffer; + + public BufferRockerOutput(ByteBuffer buffer) { + this.buffer = buffer; + } + + @Override + public ContentType getContentType() { + return ContentType.RAW; + } + + @Override + public Charset getCharset() { + return StandardCharsets.UTF_8; + } + + @Override + public BufferRockerOutput w(String string) throws IOException { + buffer.put(string.getBytes(getCharset())); + return this; + } + + @Override + public BufferRockerOutput w(byte[] bytes) throws IOException { + buffer.put(bytes); + return this; + } + + @Override + public int getByteLength() { + return buffer.remaining(); + } + + public ByteBuffer toBuffer() { + return buffer.flip(); + } + + public static RockerOutputFactory factory() { + var cache = new ThreadLocal() { + @Override + protected BufferRockerOutput initialValue() { + return new BufferRockerOutput(ByteBuffer.allocateDirect(2048)); + } + }; + return (contentType, charsetName) -> cache.get().reset(); + } + + private BufferRockerOutput reset() { + buffer.clear(); + return this; + } +} From 03c1c5c2830aca23f2e29e7f6e46aaaf4ed8b30d Mon Sep 17 00:00:00 2001 From: Ilya Nemtsev Date: Tue, 16 Jul 2024 22:49:35 +0700 Subject: [PATCH 45/62] [Ktor] Latest Ktor, serializer, html dsl versions (#9128) * latest Ktor, serializer, html dsl versions jvm runtime is now 17 Update README.md modernized all ktor tests to jvm 17 and latest ktor small pgclient memory optimizations big cleanup, removed pg-reactive-client, since it's evolution is already being tested a small memory optimization * fixed obsolete config * cleaned up legacy test --- frameworks/Kotlin/ktor/benchmark_config.json | 23 ---- frameworks/Kotlin/ktor/config.toml | 17 --- .../Kotlin/ktor/ktor-asyncdb/build.gradle | 41 ------ .../Kotlin/ktor/ktor-asyncdb/build.gradle.kts | 36 ++++++ .../ktor/ktor-asyncdb/gradle.properties | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../ktor/ktor-asyncdb/src/main/kotlin/main.kt | 118 ++++++------------ frameworks/Kotlin/ktor/ktor-cio.dockerfile | 4 +- .../Kotlin/ktor/ktor-exposed-dao.dockerfile | 2 +- .../Kotlin/ktor/ktor-exposed-dsl.dockerfile | 2 +- .../ktor/ktor-exposed/app/build.gradle.kts | 10 +- frameworks/Kotlin/ktor/ktor-jasync.dockerfile | 4 +- frameworks/Kotlin/ktor/ktor-jetty.dockerfile | 4 +- .../Kotlin/ktor/ktor-pgclient.dockerfile | 4 +- .../ktor/ktor-pgclient/build.gradle.kts | 25 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../ktor-pgclient/src/main/kotlin/main.kt | 28 +++-- .../Kotlin/ktor/ktor-reactivepg.dockerfile | 13 -- frameworks/Kotlin/ktor/ktor.dockerfile | 6 +- frameworks/Kotlin/ktor/ktor/README.md | 4 +- frameworks/Kotlin/ktor/ktor/pom.xml | 19 ++- .../org/jetbrains/ktor/benchmarks/Hello.kt | 23 ++-- 22 files changed, 156 insertions(+), 235 deletions(-) delete mode 100644 frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle create mode 100644 frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts delete mode 100644 frameworks/Kotlin/ktor/ktor-reactivepg.dockerfile diff --git a/frameworks/Kotlin/ktor/benchmark_config.json b/frameworks/Kotlin/ktor/benchmark_config.json index f675237f4b9..3a213a240ba 100644 --- a/frameworks/Kotlin/ktor/benchmark_config.json +++ b/frameworks/Kotlin/ktor/benchmark_config.json @@ -94,29 +94,6 @@ "notes": "", "versus": "netty" }, - "reactivepg": { - "json_url": "/json", - "plaintext_url": "/plaintext", - "db_url": "/db", - "query_url": "/query/?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "Ktor", - "language": "Kotlin", - "flavor": "None", - "orm": "Raw", - "platform": "None", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "Ktor-reactivepg", - "notes": "", - "versus": "netty" - }, "pgclient": { "plaintext_url": "/plaintext", "json_url": "/json", diff --git a/frameworks/Kotlin/ktor/config.toml b/frameworks/Kotlin/ktor/config.toml index 6077323686d..1c58e63c73f 100644 --- a/frameworks/Kotlin/ktor/config.toml +++ b/frameworks/Kotlin/ktor/config.toml @@ -35,23 +35,6 @@ platform = "None" webserver = "None" versus = "netty" -[reactivepg] -urls.plaintext = "/plaintext" -urls.json = "/json" -urls.db = "/db" -urls.query = "/query/?queries=" -urls.update = "/updates?queries=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Raw" -platform = "None" -webserver = "None" -versus = "netty" - [cio] urls.plaintext = "/plaintext" urls.json = "/json" diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle b/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle deleted file mode 100644 index 9a7b3bf67ee..00000000000 --- a/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle +++ /dev/null @@ -1,41 +0,0 @@ -plugins { - id "java" - id "application" - id 'org.jetbrains.kotlin.jvm' - id 'kotlinx-serialization' - id 'com.github.johnrengelman.shadow' version '4.0.3' -} - -group 'org.jetbrains.ktor' -version '1.0-SNAPSHOT' - -mainClassName = "MainKt" - -repositories { - mavenCentral() - jcenter() - maven { url "https://kotlin.bintray.com/kotlinx" } -} - -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1" - compile "io.ktor:ktor-server-netty:$ktor_version" - compile "io.ktor:ktor-html-builder:$ktor_version" - compile "com.github.jasync-sql:jasync-postgresql:0.9.39" - compile "io.reactiverse:reactive-pg-client:0.11.3" - compile 'io.vertx:vertx-lang-kotlin-coroutines:3.7.0' -} - -compileKotlin { - kotlinOptions.jvmTarget = "1.8" -} -compileTestKotlin { - kotlinOptions.jvmTarget = "1.8" -} - -shadowJar { - baseName = "bench" - classifier = null - version = null -} diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts new file mode 100644 index 00000000000..61cedf013ce --- /dev/null +++ b/frameworks/Kotlin/ktor/ktor-asyncdb/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + application + kotlin("jvm") version "1.9.22" + kotlin("plugin.serialization") version "2.0.0" + id("com.github.johnrengelman.shadow") version "8.1.0" +} + +group = "org.jetbrains.ktor" +version = "1.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +application { + mainClass.set("MainKt") +} + +val ktor_version = "2.3.12" +val kotlinx_serialization_version = "1.6.3" +val vertx_pg_client = "4.5.8" + +dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinx_serialization_version") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") + implementation("io.ktor:ktor-server-netty:$ktor_version") + implementation("io.ktor:ktor-server-default-headers:$ktor_version") + implementation("io.ktor:ktor-server-html-builder:$ktor_version") + implementation("com.github.jasync-sql:jasync-postgresql:2.2.0") +} + +tasks.shadowJar { + archiveBaseName.set("bench") + archiveClassifier.set("") + archiveVersion.set("") +} diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/gradle.properties b/frameworks/Kotlin/ktor/ktor-asyncdb/gradle.properties index f8ca4442eea..5790d58ceda 100644 --- a/frameworks/Kotlin/ktor/ktor-asyncdb/gradle.properties +++ b/frameworks/Kotlin/ktor/ktor-asyncdb/gradle.properties @@ -1,4 +1,4 @@ kotlin.code.style=official -kotlin_version=1.3.31 -ktor_version=1.2.0 +kotlin_version=1.9.22 +ktor_version=2.3.12 diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/ktor/ktor-asyncdb/gradle/wrapper/gradle-wrapper.properties index e15293214f9..3d66c176054 100644 --- a/frameworks/Kotlin/ktor/ktor-asyncdb/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/ktor/ktor-asyncdb/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip diff --git a/frameworks/Kotlin/ktor/ktor-asyncdb/src/main/kotlin/main.kt b/frameworks/Kotlin/ktor/ktor-asyncdb/src/main/kotlin/main.kt index ca7d9e5713e..e9f4221d8ed 100644 --- a/frameworks/Kotlin/ktor/ktor-asyncdb/src/main/kotlin/main.kt +++ b/frameworks/Kotlin/ktor/ktor-asyncdb/src/main/kotlin/main.kt @@ -1,28 +1,21 @@ import com.github.jasync.sql.db.ConnectionPoolConfiguration +import com.github.jasync.sql.db.QueryResult import com.github.jasync.sql.db.SuspendingConnection import com.github.jasync.sql.db.asSuspending import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder -import io.ktor.application.call -import io.ktor.application.install -import io.ktor.features.DefaultHeaders -import io.ktor.html.Placeholder -import io.ktor.html.Template -import io.ktor.html.insert -import io.ktor.html.respondHtmlTemplate import io.ktor.http.ContentType -import io.ktor.response.respondText -import io.ktor.routing.get -import io.ktor.routing.routing +import io.ktor.server.application.* import io.ktor.server.engine.embeddedServer +import io.ktor.server.html.* import io.ktor.server.netty.Netty -import io.reactiverse.kotlin.pgclient.getConnectionAwait -import io.reactiverse.kotlin.pgclient.preparedBatchAwait -import io.reactiverse.kotlin.pgclient.preparedQueryAwait -import io.reactiverse.pgclient.* +import io.ktor.server.plugins.defaultheaders.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import kotlinx.coroutines.* import kotlinx.html.* import kotlinx.serialization.Serializable -import kotlinx.serialization.json.JSON -import kotlinx.serialization.list +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json import java.lang.IllegalArgumentException import kotlin.random.Random import kotlin.random.nextInt @@ -44,73 +37,48 @@ interface Repository { } class JasyncRepository() : Repository { - private val dbConfig: ConnectionPoolConfiguration - private val db: SuspendingConnection - - init { - dbConfig = ConnectionPoolConfiguration( - "tfb-database", - database = "hello_world", - username = "benchmarkdbuser", - password = "benchmarkdbpass", - maxActiveConnections = 64 - ) - db = PostgreSQLConnectionBuilder.createConnectionPool(dbConfig).asSuspending + companion object { + const val WORLD_QUERY = "select id, randomNumber from world where id = ?" + const val FORTUNES_QUERY = "select id, message from fortune" + const val UPDATE_QUERY = "update world set randomNumber = ? where id = ?" } + private val dbConfig: ConnectionPoolConfiguration = ConnectionPoolConfiguration( + "tfb-database", + database = "hello_world", + username = "benchmarkdbuser", + password = "benchmarkdbpass", + maxActiveConnections = 64 + ) + private val db: SuspendingConnection = PostgreSQLConnectionBuilder.createConnectionPool(dbConfig).asSuspending + override suspend fun getWorld(): World { val worldId = rand.nextInt(1, 10000) - val result = db.sendPreparedStatement("select id, randomNumber from world where id = ?", listOf(worldId)) + val result = db.sendPreparedStatement(WORLD_QUERY, listOf(worldId)) val row = result.rows.first() return World(row.getInt(0)!!, row.getInt(1)!!) } override suspend fun getFortunes(): List { - val results = db.sendPreparedStatement("select id, message from fortune") + val results = db.sendPreparedStatement(FORTUNES_QUERY) return results.rows.map { Fortune(it.getInt(0)!!, it.getString(1)!!) } } override suspend fun updateWorlds(worlds: List) { - worlds.forEach { world -> - db.sendPreparedStatement( - "update world set randomNumber = ? where id = ?", - listOf(world.randomNumber, world.id) - ) - } - } -} + coroutineScope { + val jobs = ArrayList>(worlds.size) + worlds.forEach { world -> + val deferred = async(Dispatchers.IO) { + db.sendPreparedStatement( + UPDATE_QUERY, + listOf(world.randomNumber, world.id) + ) + } + jobs.add(deferred) + } -class ReactivePGRepository : Repository { - private val db: PgPool - - init { - val poolOptions = PgPoolOptions() - poolOptions.apply { - host = "tfb-database" - database = "hello_world" - user = "benchmarkdbuser" - password = "benchmarkdbpass" - maxSize = 64 - cachePreparedStatements = true + jobs.awaitAll() } - db = PgClient.pool(poolOptions) - } - - override suspend fun getFortunes(): List { - val results = db.preparedQueryAwait("select id, message from fortune") - return results.map { Fortune(it.getInteger(0), it.getString(1)) } - } - - override suspend fun getWorld(): World { - val worldId = rand.nextInt(1, 10000) - val result = db.preparedQueryAwait("select id, randomNumber from world where id = $1", Tuple.of(worldId)) - val row = result.first() - return World(row.getInteger(0), row.getInteger(1)!!) - } - - override suspend fun updateWorlds(worlds: List) { - val batch = worlds.map { Tuple.of(it.id, it.randomNumber) } - db.preparedBatchAwait("update world set randomNumber = $1 where id = $2", batch) } } @@ -132,7 +100,7 @@ class MainTemplate : Template { } } -class FortuneTemplate(val fortunes: List, val main: MainTemplate = MainTemplate()) : Template { +class FortuneTemplate(private val fortunes: List, private val main: MainTemplate = MainTemplate()) : Template { override fun HTML.apply() { insert(main) { content { @@ -156,13 +124,9 @@ class FortuneTemplate(val fortunes: List, val main: MainTemplate = Main fun main(args: Array) { val db = when(args.firstOrNull()) { "jasync-sql" -> JasyncRepository() - "reactive-pg" -> ReactivePGRepository() else -> throw IllegalArgumentException("Must specify a postgres client") } - val messageSerializer = Message.serializer() - val worldSerializer = World.serializer() - val server = embeddedServer(Netty, 8080, configure = { shareWorkGroup = true }) { @@ -174,19 +138,19 @@ fun main(args: Array) { get("/json") { call.respondText( - JSON.stringify(messageSerializer, Message("Hello, World!")), + Json.encodeToString(Message("Hello, World!")), ContentType.Application.Json ) } get("/db") { - call.respondText(JSON.stringify(worldSerializer, db.getWorld()), ContentType.Application.Json) + call.respondText(Json.encodeToString(db.getWorld()), ContentType.Application.Json) } get("/query/") { val queries = call.parameters["queries"]?.toBoxedInt(1..500) ?: 1 val worlds = (1..queries).map { db.getWorld() } - call.respondText(JSON.stringify(worldSerializer.list, worlds), ContentType.Application.Json) + call.respondText(Json.encodeToString(worlds), ContentType.Application.Json) } get("/fortunes") { @@ -204,7 +168,7 @@ fun main(args: Array) { db.updateWorlds(newWorlds) - call.respondText(JSON.stringify(worldSerializer.list, newWorlds), ContentType.Application.Json) + call.respondText(Json.encodeToString(newWorlds), ContentType.Application.Json) } } } diff --git a/frameworks/Kotlin/ktor/ktor-cio.dockerfile b/frameworks/Kotlin/ktor/ktor-cio.dockerfile index 6ba40b6eccc..33059ec9fd4 100644 --- a/frameworks/Kotlin/ktor/ktor-cio.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-cio.dockerfile @@ -1,10 +1,10 @@ -FROM maven:3.6.1-jdk-11-slim as maven +FROM maven:3.9.7-amazoncorretto-17-debian as maven WORKDIR /ktor COPY ktor/pom.xml pom.xml COPY ktor/src src RUN mvn clean package -q -FROM openjdk:11.0.3-jdk-stretch +FROM amazoncorretto:17.0.11-al2023-headless WORKDIR /ktor COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-cio-bundle.jar app.jar diff --git a/frameworks/Kotlin/ktor/ktor-exposed-dao.dockerfile b/frameworks/Kotlin/ktor/ktor-exposed-dao.dockerfile index 9867cf2931c..e12a664f8dc 100644 --- a/frameworks/Kotlin/ktor/ktor-exposed-dao.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-exposed-dao.dockerfile @@ -1,4 +1,4 @@ -FROM gradle:8.0.2-jdk11 +FROM gradle:jdk17 WORKDIR /ktor-exposed COPY ktor-exposed/settings.gradle.kts settings.gradle.kts diff --git a/frameworks/Kotlin/ktor/ktor-exposed-dsl.dockerfile b/frameworks/Kotlin/ktor/ktor-exposed-dsl.dockerfile index 5b7f7fe722a..f65069e6b78 100644 --- a/frameworks/Kotlin/ktor/ktor-exposed-dsl.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-exposed-dsl.dockerfile @@ -1,4 +1,4 @@ -FROM gradle:8.0.2-jdk11 +FROM gradle:jdk17 WORKDIR /ktor-exposed COPY ktor-exposed/settings.gradle.kts settings.gradle.kts diff --git a/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts index 4d798b53bcf..60f4dab3b17 100644 --- a/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts +++ b/frameworks/Kotlin/ktor/ktor-exposed/app/build.gradle.kts @@ -1,7 +1,7 @@ plugins { - kotlin("jvm") version "1.8.10" - kotlin("plugin.serialization") version "1.8.10" application + kotlin("jvm") version "1.9.22" + kotlin("plugin.serialization") version "2.0.0" id("com.github.johnrengelman.shadow") version "8.1.0" } @@ -9,9 +9,9 @@ repositories { mavenCentral() } -val ktorVersion = "2.2.3" -val kotlinxSerializationVersion = "1.5.0" -val exposedVersion = "0.41.1" +val ktorVersion = "2.3.12" +val kotlinxSerializationVersion = "1.6.3" +val exposedVersion = "0.52.0" dependencies { implementation("io.ktor:ktor-server-core:$ktorVersion") diff --git a/frameworks/Kotlin/ktor/ktor-jasync.dockerfile b/frameworks/Kotlin/ktor/ktor-jasync.dockerfile index 38649f62693..8c66e81ea4e 100644 --- a/frameworks/Kotlin/ktor/ktor-jasync.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-jasync.dockerfile @@ -1,7 +1,7 @@ -FROM openjdk:11.0.3-jdk-stretch +FROM maven:3.9.7-amazoncorretto-17-debian WORKDIR /app COPY ktor-asyncdb/gradle gradle -COPY ktor-asyncdb/build.gradle build.gradle +COPY ktor-asyncdb/build.gradle.kts build.gradle.kts COPY ktor-asyncdb/gradle.properties gradle.properties COPY ktor-asyncdb/gradlew gradlew COPY ktor-asyncdb/settings.gradle settings.gradle diff --git a/frameworks/Kotlin/ktor/ktor-jetty.dockerfile b/frameworks/Kotlin/ktor/ktor-jetty.dockerfile index 3976e5f2df9..e753d7cc442 100644 --- a/frameworks/Kotlin/ktor/ktor-jetty.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-jetty.dockerfile @@ -1,10 +1,10 @@ -FROM maven:3.6.1-jdk-11-slim as maven +FROM maven:3.9.7-amazoncorretto-17-debian as maven WORKDIR /ktor COPY ktor/pom.xml pom.xml COPY ktor/src src RUN mvn clean package -q -FROM openjdk:11.0.3-jdk-stretch +FROM amazoncorretto:17.0.11-al2023-headless WORKDIR /ktor COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-jetty-bundle.jar app.jar diff --git a/frameworks/Kotlin/ktor/ktor-pgclient.dockerfile b/frameworks/Kotlin/ktor/ktor-pgclient.dockerfile index be123f07e6f..0cf012e7596 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient.dockerfile +++ b/frameworks/Kotlin/ktor/ktor-pgclient.dockerfile @@ -1,4 +1,4 @@ -FROM openjdk:11.0.3-jdk-stretch as build +FROM maven:3.9.7-amazoncorretto-17-debian as build WORKDIR /app COPY ktor-pgclient/gradle gradle COPY ktor-pgclient/build.gradle.kts build.gradle.kts @@ -6,7 +6,7 @@ COPY ktor-pgclient/gradlew gradlew COPY ktor-pgclient/src src RUN /app/gradlew --no-daemon shadowJar -FROM openjdk:11.0.3-jdk-slim +FROM amazoncorretto:17.0.11-al2023-headless WORKDIR /app COPY --from=build /app/build/libs/ktor-pgclient.jar ktor-pgclient.jar diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts b/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts index f57c372b49f..f080b64d69f 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts +++ b/frameworks/Kotlin/ktor/ktor-pgclient/build.gradle.kts @@ -1,8 +1,8 @@ plugins { application - kotlin("jvm") version "1.6.10" - id("org.jetbrains.kotlin.plugin.serialization") version "1.6.21" - id("com.github.johnrengelman.shadow") version "7.1.2" + kotlin("jvm") version "1.9.22" + kotlin("plugin.serialization") version "2.0.0" + id("com.github.johnrengelman.shadow") version "8.1.0" } group = "org.jetbrains.ktor" @@ -16,19 +16,20 @@ application { mainClass.set("MainKt") } +val ktor_version = "2.3.12" + dependencies { - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") - implementation("io.ktor:ktor-server-netty:2.0.1") - implementation("io.ktor:ktor-server-html-builder-jvm:2.0.1") - implementation("io.ktor:ktor-server-default-headers-jvm:2.0.1") - implementation("io.vertx:vertx-pg-client:4.2.3") - implementation("io.vertx:vertx-lang-kotlin:4.2.3") - implementation("io.vertx:vertx-lang-kotlin-coroutines:4.2.3") + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3") + implementation("io.ktor:ktor-server-netty:$ktor_version") + implementation("io.ktor:ktor-server-html-builder-jvm:$ktor_version") + implementation("io.ktor:ktor-server-default-headers-jvm:$ktor_version") + implementation("io.vertx:vertx-pg-client:4.5.8") + implementation("io.vertx:vertx-lang-kotlin:4.5.8") + implementation("io.vertx:vertx-lang-kotlin-coroutines:4.5.8") } tasks.withType().configureEach { - kotlinOptions.jvmTarget = "11" + kotlinOptions.jvmTarget = "17" } tasks.shadowJar { diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties index aa991fceae6..e1bef7e873c 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Kotlin/ktor/ktor-pgclient/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt b/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt index b4f7dc89615..c8e74244f99 100644 --- a/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt +++ b/frameworks/Kotlin/ktor/ktor-pgclient/src/main/kotlin/main.kt @@ -7,6 +7,8 @@ import io.ktor.server.plugins.defaultheaders.* import io.ktor.server.response.* import io.ktor.server.routing.* import io.vertx.kotlin.coroutines.await +import io.vertx.kotlin.coroutines.coAwait +import io.vertx.pgclient.PgBuilder import io.vertx.pgclient.PgConnectOptions import io.vertx.pgclient.PgPool import io.vertx.sqlclient.PoolOptions @@ -35,6 +37,12 @@ interface Repository { } class PgclientRepository : Repository { + companion object { + private const val FORTUNES_QUERY = "select id, message from FORTUNE" + private const val SELECT_WORLD_QUERY = "SELECT id, randomnumber from WORLD where id=$1" + private const val UPDATE_WORLD_QUERY = "UPDATE WORLD SET randomnumber=$1 WHERE id=$2" + } + private val connectOptions = PgConnectOptions().apply { port = 5432 @@ -47,21 +55,23 @@ class PgclientRepository : Repository { } private val poolOptions = PoolOptions() - private val client = ThreadLocal.withInitial { PgPool.client(connectOptions, poolOptions) } - private fun client() = client.get() + private val client = PgBuilder.client() + .with(poolOptions) + .connectingTo(connectOptions) + .build() override suspend fun getFortunes(): List { - val results = client().preparedQuery("select id, message from fortune").execute().await() + val results = client.preparedQuery(FORTUNES_QUERY).execute().coAwait() return results.map { Fortune(it.getInteger(0), it.getString(1)) } } override suspend fun getWorld(): World { val worldId = rand.nextInt(1, 10001) val result = - client() - .preparedQuery("select id, randomNumber from world where id = $1") + client + .preparedQuery(SELECT_WORLD_QUERY) .execute(Tuple.of(worldId)) - .await() + .coAwait() val row = result.first() return World(row.getInteger(0), row.getInteger(1)!!) } @@ -69,10 +79,10 @@ class PgclientRepository : Repository { override suspend fun updateWorlds(worlds: List) { // Worlds should be sorted before being batch-updated with to avoid data race and deadlocks. val batch = worlds.sortedBy { it.id }.map { Tuple.of(it.randomNumber, it.id) } - client() - .preparedQuery("update world set randomNumber = $1 where id = $2") + client + .preparedQuery(UPDATE_WORLD_QUERY) .executeBatch(batch) - .await() + .coAwait() } } diff --git a/frameworks/Kotlin/ktor/ktor-reactivepg.dockerfile b/frameworks/Kotlin/ktor/ktor-reactivepg.dockerfile deleted file mode 100644 index 41476da82ba..00000000000 --- a/frameworks/Kotlin/ktor/ktor-reactivepg.dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM openjdk:11.0.3-jdk-stretch -WORKDIR /app -COPY ktor-asyncdb/gradle gradle -COPY ktor-asyncdb/build.gradle build.gradle -COPY ktor-asyncdb/gradle.properties gradle.properties -COPY ktor-asyncdb/gradlew gradlew -COPY ktor-asyncdb/settings.gradle settings.gradle -COPY ktor-asyncdb/src src -RUN /app/gradlew --no-daemon shadowJar - -EXPOSE 9090 - -CMD ["java", "-server", "-XX:+UseParallelGC", "-Xms2G","-Xmx2G", "-jar", "/app/build/libs/bench.jar", "reactive-pg"] diff --git a/frameworks/Kotlin/ktor/ktor.dockerfile b/frameworks/Kotlin/ktor/ktor.dockerfile index 36aa32fd8c2..1558d312736 100644 --- a/frameworks/Kotlin/ktor/ktor.dockerfile +++ b/frameworks/Kotlin/ktor/ktor.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.6.1-jdk-11-slim as maven +FROM maven:3.9.7-amazoncorretto-17-debian as maven WORKDIR /ktor COPY ktor/pom.xml pom.xml COPY ktor/src src RUN mvn clean package -q -FROM openjdk:11.0.3-jdk-stretch +FROM amazoncorretto:17.0.11-al2023-headless WORKDIR /ktor COPY --from=maven /ktor/target/tech-empower-framework-benchmark-1.0-SNAPSHOT-netty-bundle.jar app.jar EXPOSE 9090 -CMD ["java", "-server","-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-XX:+AlwaysPreTouch", "-jar", "app.jar"] +CMD ["java", "-server","-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AlwaysPreTouch", "-jar", "app.jar"] diff --git a/frameworks/Kotlin/ktor/ktor/README.md b/frameworks/Kotlin/ktor/ktor/README.md index 07cb92359c2..e3c141a70e0 100644 --- a/frameworks/Kotlin/ktor/ktor/README.md +++ b/frameworks/Kotlin/ktor/ktor/README.md @@ -5,13 +5,13 @@ More information is available at [ktor.io](http://ktor.io). # Setup -* Java 8 +* Java 17 * MySQL server # Requirements * Maven 3 -* JDK 8 +* JDK 17 * Kotlin * ktor * netty diff --git a/frameworks/Kotlin/ktor/ktor/pom.xml b/frameworks/Kotlin/ktor/ktor/pom.xml index 35ad4547a16..a794bb59fe3 100644 --- a/frameworks/Kotlin/ktor/ktor/pom.xml +++ b/frameworks/Kotlin/ktor/ktor/pom.xml @@ -12,10 +12,10 @@ org.jetbrains.ktor tech-empower-framework-benchmark - 1.6.21 - 2.0.1 - 1.3.2 - 0.7.3 + 1.9.22 + 2.3.11 + 1.6.3 + 0.11.0 UTF-8 5.0.0 1.2.13 @@ -24,11 +24,6 @@ - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - org.jetbrains.kotlin kotlin-reflect @@ -85,17 +80,17 @@ io.ktor ktor-server-netty-jvm - 2.0.0 + ${ktor.version} io.ktor ktor-server-jetty-jvm - 2.0.0 + ${ktor.version} io.ktor ktor-server-cio-jvm - 2.0.0 + ${ktor.version} diff --git a/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt b/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt index b767e0605f5..82bdd34bc66 100644 --- a/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt +++ b/frameworks/Kotlin/ktor/ktor/src/main/kotlin/org/jetbrains/ktor/benchmarks/Hello.kt @@ -9,12 +9,14 @@ import io.ktor.server.html.* import io.ktor.server.plugins.defaultheaders.* import io.ktor.server.response.* import io.ktor.server.routing.* -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext +import kotlinx.coroutines.* import kotlinx.html.* import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import org.jetbrains.ktor.benchmarks.Constants.FORTUNES_QUERY +import org.jetbrains.ktor.benchmarks.Constants.UPDATE_QUERY +import org.jetbrains.ktor.benchmarks.Constants.WORLD_QUERY import java.sql.Connection import java.util.concurrent.ThreadLocalRandom @@ -30,7 +32,7 @@ data class Fortune(val id: Int, var message: String) fun Application.main() { val dbRows = 10000 val poolSize = 48 - val pool by lazy { HikariDataSource(HikariConfig().apply { configurePostgres(poolSize) }) } + val pool = HikariDataSource(HikariConfig().apply { configurePostgres(poolSize) }) val databaseDispatcher = Dispatchers.IO install(DefaultHeaders) @@ -51,7 +53,7 @@ fun Application.main() { val world = withContext(databaseDispatcher) { pool.connection.use { connection -> - connection.prepareStatement("SELECT id, randomNumber FROM World WHERE id = ?").use { statement -> + connection.prepareStatement(WORLD_QUERY).use { statement -> statement.setInt(1, random.nextInt(dbRows) + 1) statement.executeQuery().use { rs -> @@ -67,7 +69,7 @@ fun Application.main() { fun Connection.selectWorlds(queries: Int, random: ThreadLocalRandom): List { val result = ArrayList(queries) - prepareStatement("SELECT id, randomNumber FROM World WHERE id = ?").use { statement -> + prepareStatement(WORLD_QUERY).use { statement -> repeat(queries) { statement.setInt(1, random.nextInt(dbRows) + 1) @@ -96,7 +98,7 @@ fun Application.main() { val result = mutableListOf() withContext(databaseDispatcher) { pool.connection.use { connection -> - connection.prepareStatement("SELECT id, message FROM fortune").use { statement -> + connection.prepareStatement(FORTUNES_QUERY).use { statement -> statement.executeQuery().use { rs -> while (rs.next()) { result += Fortune(rs.getInt(1), rs.getString(2)) @@ -137,7 +139,7 @@ fun Application.main() { result.forEach { it.randomNumber = random.nextInt(dbRows) + 1 } - connection.prepareStatement("UPDATE World SET randomNumber = ? WHERE id = ?") + connection.prepareStatement(UPDATE_QUERY) .use { updateStatement -> for ((id, randomNumber) in result) { updateStatement.setInt(1, randomNumber) @@ -182,3 +184,10 @@ fun HikariConfig.configureMySql(poolSize: Int) { fun ApplicationCall.queries() = request.queryParameters["queries"]?.toIntOrNull()?.coerceIn(1, 500) ?: 1 + + +object Constants { + const val WORLD_QUERY = "SELECT id, randomNumber FROM World WHERE id = ?" + const val FORTUNES_QUERY = "SELECT id, message FROM fortune" + const val UPDATE_QUERY = "UPDATE World SET randomNumber = ? WHERE id = ?" +} \ No newline at end of file From 9ab75acf9c341630cfeae907f2f3b2c3d70930cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:11:29 +0000 Subject: [PATCH 46/62] Bump openssl from 0.10.61 to 0.10.66 in /frameworks/Rust/axum Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.61 to 0.10.66. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.61...openssl-v0.10.66) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frameworks/Rust/axum/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frameworks/Rust/axum/Cargo.lock b/frameworks/Rust/axum/Cargo.lock index 3d63ad71fb7..3a9dba5fb18 100644 --- a/frameworks/Rust/axum/Cargo.lock +++ b/frameworks/Rust/axum/Cargo.lock @@ -1379,9 +1379,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.61" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -1411,9 +1411,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.97" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", From 7e12fbc94fff02c257fd18a824c563cf9e51bd3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:41:22 +0000 Subject: [PATCH 47/62] Bump io.undertow:undertow-core in /frameworks/Java/light-java Bumps [io.undertow:undertow-core](https://github.com/undertow-io/undertow) from 2.3.12.Final to 2.3.15.Final. - [Release notes](https://github.com/undertow-io/undertow/releases) - [Commits](https://github.com/undertow-io/undertow/compare/2.3.12.Final...2.3.15.Final) --- updated-dependencies: - dependency-name: io.undertow:undertow-core dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Java/light-java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Java/light-java/pom.xml b/frameworks/Java/light-java/pom.xml index 0d76eb4e631..787dc1253bb 100644 --- a/frameworks/Java/light-java/pom.xml +++ b/frameworks/Java/light-java/pom.xml @@ -25,7 +25,7 @@ 11 2.0.1 1.3.12 - 2.3.12.Final + 2.3.15.Final 3.3.1 8.0.28 42.7.2 From 8710bc806824912856ece4650e415009b30f91f3 Mon Sep 17 00:00:00 2001 From: Vladimir Shchur Date: Tue, 23 Jul 2024 20:44:30 +0300 Subject: [PATCH 48/62] [F#/Oxpecker] Several improvements (#9170) * [F#/Oxpecker] Change fortunes serialization to chunked * [F#/Oxpecker] Database query improvements * [F#/Oxpecker] Disabled config file changes --- .../FSharp/oxpecker/oxpecker.dockerfile | 1 + frameworks/FSharp/oxpecker/src/App/App.fsproj | 2 +- frameworks/FSharp/oxpecker/src/App/Db.fs | 23 +++++++++++++------ frameworks/FSharp/oxpecker/src/App/Program.fs | 2 +- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/frameworks/FSharp/oxpecker/oxpecker.dockerfile b/frameworks/FSharp/oxpecker/oxpecker.dockerfile index 35a8c509c96..4f6676892c3 100644 --- a/frameworks/FSharp/oxpecker/oxpecker.dockerfile +++ b/frameworks/FSharp/oxpecker/oxpecker.dockerfile @@ -6,6 +6,7 @@ RUN dotnet publish -c Release -o out FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime ENV DOTNET_ReadyToRun 0 +ENV ASPNETCORE_hostBuilder__reloadConfigOnChange false ENV URLS http://+:8080 diff --git a/frameworks/FSharp/oxpecker/src/App/App.fsproj b/frameworks/FSharp/oxpecker/src/App/App.fsproj index f01c367f95f..1b6f8b76cd3 100644 --- a/frameworks/FSharp/oxpecker/src/App/App.fsproj +++ b/frameworks/FSharp/oxpecker/src/App/App.fsproj @@ -13,7 +13,7 @@ - + \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/src/App/Db.fs b/frameworks/FSharp/oxpecker/src/App/Db.fs index 498721b2b2e..2c471bada1d 100644 --- a/frameworks/FSharp/oxpecker/src/App/Db.fs +++ b/frameworks/FSharp/oxpecker/src/App/Db.fs @@ -21,19 +21,19 @@ module Db = return result } - let private createReadCommand (connection: DbConnection) = + let private createReadCommand (connection: NpgsqlConnection) = let cmd = connection.CreateCommand( CommandText = "SELECT id, randomnumber FROM world WHERE id = @Id" ) - let id = cmd.CreateParameter( + let id = NpgsqlParameter( ParameterName = "@Id", DbType = DbType.Int32, - Value = Random.Shared.Next(1, 10001) + TypedValue = Random.Shared.Next(1, 10001) ) cmd.Parameters.Add(id) |> ignore cmd - let private readSingleRow (cmd: DbCommand) = + let private readSingleRow (cmd: NpgsqlCommand) = task { use! rdr = cmd.ExecuteReaderAsync(CommandBehavior.SingleRow) let! _ = rdr.ReadAsync() @@ -83,12 +83,21 @@ module Db = | q -> q - let private generateParameters (results: World[]) (command: DbCommand) = + // fill cache + let _ = [| 0..maxBatch |] |> Array.map batchUpdateString + + let private paramNames = + seq { 0..maxBatch*2 } + |> Seq.map (fun i -> struct($"@Rn_{i}", $"@Id_{i}")) + |> Seq.toArray + + let private generateParameters (results: World[]) (command: NpgsqlCommand) = for i in 0..results.Length-1 do let randomNumber = Random.Shared.Next(1, 10001) - let random = command.CreateParameter(ParameterName = $"@Rn_{i}", DbType = DbType.Int32, Value = randomNumber) + let struct(rnParamName, idParamName) = paramNames[i] + let random = NpgsqlParameter(ParameterName = rnParamName, DbType = DbType.Int32, TypedValue = randomNumber) command.Parameters.Add(random) |> ignore - let id = command.CreateParameter(ParameterName = $"@Id_{i}", DbType = DbType.Int32, Value = results[i].id) + let id = NpgsqlParameter(ParameterName = idParamName, DbType = DbType.Int32, TypedValue = results[i].id) command.Parameters.Add(id) |> ignore results[i] <- { results[i] with randomnumber = randomNumber } diff --git a/frameworks/FSharp/oxpecker/src/App/Program.fs b/frameworks/FSharp/oxpecker/src/App/Program.fs index dcfd3c53206..09ba84b4fae 100644 --- a/frameworks/FSharp/oxpecker/src/App/Program.fs +++ b/frameworks/FSharp/oxpecker/src/App/Program.fs @@ -49,7 +49,7 @@ module HttpHandlers = let rec private renderFortunes (ctx: HttpContext) (data: ResizeArray) = data.Add extra data.Sort FortuneComparer - data |> HtmlViews.fortunes |> ctx.WriteHtmlView + data |> HtmlViews.fortunes |> ctx.WriteHtmlViewChunked let fortunes : EndpointHandler = fun ctx -> From 1a62761218245423a85fc42794588de29ad3638e Mon Sep 17 00:00:00 2001 From: Julien Viet Date: Tue, 23 Jul 2024 19:45:09 +0200 Subject: [PATCH 49/62] Upgrade to Vert.x 4.5.9 and use the new data object JSON serializer library, in addition perform a few tweaks to the server. (#9171) --- frameworks/Java/vertx/pom.xml | 19 +- .../Java/vertx/src/main/java/vertx/App.java | 252 +++++++++--------- .../main/java/vertx/model/CachedWorld.java | 15 +- .../src/main/java/vertx/model/Fortune.java | 17 +- .../src/main/java/vertx/model/Message.java | 23 +- .../src/main/java/vertx/model/World.java | 19 +- .../main/java/vertx/model/package-info.java | 4 + .../Java/vertx/vertx-postgres.dockerfile | 1 + frameworks/Java/vertx/vertx.dockerfile | 2 +- 9 files changed, 194 insertions(+), 158 deletions(-) create mode 100644 frameworks/Java/vertx/src/main/java/vertx/model/package-info.java diff --git a/frameworks/Java/vertx/pom.xml b/frameworks/Java/vertx/pom.xml index cdb3aa09f6a..12eff9d69a5 100644 --- a/frameworks/Java/vertx/pom.xml +++ b/frameworks/Java/vertx/pom.xml @@ -10,9 +10,9 @@ 17 vertx.App - 4.5.8 + 4.5.9 2.16.1 - 4.1.110.Final + 4.1.111.Final 0.0.25.Final @@ -32,6 +32,11 @@ jackson-core ${jackson.version} + + com.julienviet + jsonsergen + 0.0.4 + io.netty netty-transport-native-kqueue @@ -70,6 +75,16 @@ false + + + default-compile + + + io.vertx.codegen.CodeGenProcessor + + + + com.fizzed diff --git a/frameworks/Java/vertx/src/main/java/vertx/App.java b/frameworks/Java/vertx/src/main/java/vertx/App.java index 5e81292d8ed..5afa269ae9e 100755 --- a/frameworks/Java/vertx/src/main/java/vertx/App.java +++ b/frameworks/Java/vertx/src/main/java/vertx/App.java @@ -12,17 +12,12 @@ import io.vertx.core.http.HttpServerOptions; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.sqlclient.*; import io.vertx.sqlclient.impl.SqlClientInternal; -import vertx.model.CachedWorld; -import vertx.model.Fortune; -import vertx.model.Message; -import vertx.model.World; -import vertx.model.WorldCache; +import vertx.model.*; import vertx.rocker.BufferRockerOutput; import java.io.ByteArrayOutputStream; @@ -38,9 +33,13 @@ import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; +import java.util.stream.IntStream; public class App extends AbstractVerticle implements Handler { + private static final int NUM_PROCESSORS = Runtime.getRuntime().availableProcessors(); + private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(App.class); + /** * Returns the value of the "queries" getRequest parameter, which is an integer * bound between 1 and 500 with a default value of 1. @@ -62,7 +61,9 @@ static int getQueries(HttpServerRequest request) { } } - static Logger logger = LoggerFactory.getLogger(App.class.getName()); + private static Logger logger = LoggerFactory.getLogger(App.class.getName()); + + private static final Integer[] BOXED_RND = IntStream.range(1, 10001).boxed().toArray(Integer[]::new); private static final String PATH_PLAINTEXT = "/plaintext"; private static final String PATH_JSON = "/json"; @@ -76,7 +77,7 @@ static int getQueries(HttpServerRequest request) { private static final CharSequence RESPONSE_TYPE_PLAIN = HttpHeaders.createOptimized("text/plain"); private static final CharSequence RESPONSE_TYPE_HTML = HttpHeaders.createOptimized("text/html; charset=UTF-8"); - private static final CharSequence RESPONSE_TYPE_JSON = HttpHeaders.createOptimized("application/json"); + static final CharSequence RESPONSE_TYPE_JSON = HttpHeaders.createOptimized("application/json"); private static final String HELLO_WORLD = "Hello, world!"; private static final Buffer HELLO_WORLD_BUFFER = Buffer.buffer(HELLO_WORLD, "UTF-8"); @@ -89,14 +90,29 @@ static int getQueries(HttpServerRequest request) { private static final CharSequence HELLO_WORLD_LENGTH = HttpHeaders.createOptimized("" + HELLO_WORLD.length()); private static final CharSequence SERVER = HttpHeaders.createOptimized("vert.x"); - private static final String UPDATE_WORLD = "UPDATE world SET randomnumber=$1 WHERE id=$2"; private static final String SELECT_WORLD = "SELECT id, randomnumber from WORLD where id=$1"; private static final String SELECT_FORTUNE = "SELECT id, message from FORTUNE"; private static final String SELECT_WORLDS = "SELECT id, randomnumber from WORLD"; + public static CharSequence createDateHeader() { + return HttpHeaders.createOptimized(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now())); + } + + /** + * Returns a random integer that is a suitable value for both the {@code id} + * and {@code randomNumber} properties of a world object. + * + * @return a random world number + */ + static Integer boxedRandomWorldNumber() { + final int rndValue = ThreadLocalRandom.current().nextInt(1, 10001); + final var boxedRnd = BOXED_RND[rndValue - 1]; + assert boxedRnd.intValue() == rndValue; + return boxedRnd; + } + private HttpServer server; - private SqlClientInternal client1; - private SqlClientInternal client2; + private SqlClientInternal client; private CharSequence dateString; private CharSequence[] plaintextHeaders; @@ -105,15 +121,10 @@ static int getQueries(HttpServerRequest request) { private Throwable databaseErr; private PreparedQuery> SELECT_WORLD_QUERY; private PreparedQuery>> SELECT_FORTUNE_QUERY; - private PreparedQuery> UPDATE_WORLD_QUERY; @SuppressWarnings("unchecked") - private PreparedQuery>[] AGGREGATED_UPDATE_WORLD_QUERY = new PreparedQuery[128]; + private PreparedQuery>[] AGGREGATED_UPDATE_WORLD_QUERY = new PreparedQuery[500]; private WorldCache WORLD_CACHE; - public static CharSequence createDateHeader() { - return HttpHeaders.createOptimized(DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now())); - } - @Override public void start(Promise startPromise) throws Exception { int port = 8080; @@ -134,6 +145,7 @@ public void start(Promise startPromise) throws Exception { options.setUser(config.getString("username", "benchmarkdbuser")); options.setPassword(config.getString("password", "benchmarkdbpass")); options.setCachePreparedStatements(true); + options.setPreparedStatementCacheMaxSize(1024); options.setPipeliningLimit(100_000); // Large pipelining means less flushing and we use a single connection anyway Future clientsInit = initClients(options); clientsInit @@ -146,9 +158,9 @@ public void start(Promise startPromise) throws Exception { } private Future initClients(PgConnectOptions options) { - Future cf1 = PgConnection.connect(vertx, options) + return PgConnection.connect(vertx, options) .flatMap(conn -> { - client1 = (SqlClientInternal) conn; + client = (SqlClientInternal) conn; List> list = new ArrayList<>(); Future f1 = conn.prepare(SELECT_WORLD) .andThen(onSuccess(ps -> SELECT_WORLD_QUERY = ps.query())); @@ -165,15 +177,6 @@ private Future initClients(PgConnectOptions options) { .map(worlds -> new WorldCache(worlds.value())) .andThen(onSuccess(wc -> WORLD_CACHE = wc)); list.add(f3); - return Future.join(list); - }); - Future cf2 = PgConnection.connect(vertx, options) - .flatMap(conn -> { - client2 = (SqlClientInternal) conn; - List> list = new ArrayList<>(); - Future f1 = conn.prepare(UPDATE_WORLD) - .andThen(onSuccess(ps -> UPDATE_WORLD_QUERY = ps.query())); - list.add(f1); for (int i = 0; i < AGGREGATED_UPDATE_WORLD_QUERY.length; i++) { int idx = i; Future fut = conn @@ -183,22 +186,26 @@ private Future initClients(PgConnectOptions options) { } return Future.join(list); }); - return Future.join(cf1, cf2); } private static String buildAggregatedUpdateQuery(int len) { - StringBuilder sb = new StringBuilder(); - sb.append("UPDATE world SET randomNumber = update_data.randomNumber FROM (VALUES"); - char sep = ' '; - for (int i = 1;i <= len;i++) { - sb.append(sep).append("($").append(2 * i - 1).append("::int,$").append(2 * i).append("::int)"); - sep = ','; + StringBuilder sql = new StringBuilder(); + sql.append("UPDATE WORLD SET RANDOMNUMBER = CASE ID"); + for (int i = 0; i < len; i++) { + int offset = (i * 2) + 1; + sql.append(" WHEN $").append(offset).append(" THEN $").append(offset + 1); } - sb.append(") AS update_data (id, randomNumber) WHERE world.id = update_data.id"); - return sb.toString(); + sql.append(" ELSE RANDOMNUMBER"); + sql.append(" END WHERE ID IN ($1"); + for (int i = 1; i < len; i++) { + int offset = (i * 2) + 1; + sql.append(",$").append(offset); + } + sql.append(")"); + return sql.toString(); } - private static Handler> onSuccess(Handler handler) { + public static Handler> onSuccess(Handler handler) { return ar -> { if (ar.succeeded()) { handler.handle(ar.result()); @@ -232,8 +239,9 @@ public void handle(HttpServerRequest request) { handleCaching(request); break; default: - request.response().setStatusCode(404); - request.response().end(); + request.response() + .setStatusCode(404) + .end(); break; } } catch (Exception e) { @@ -267,22 +275,12 @@ private void handleJson(HttpServerRequest request) { .add(HEADER_CONTENT_TYPE, RESPONSE_TYPE_JSON) .add(HEADER_SERVER, SERVER) .add(HEADER_DATE, dateString); - response.end(new Message("Hello, World!").toBuffer(), NULL_HANDLER); - } - - /** - * Returns a random integer that is a suitable value for both the {@code id} - * and {@code randomNumber} properties of a world object. - * - * @return a random world number - */ - private static int randomWorld() { - return 1 + ThreadLocalRandom.current().nextInt(10000); + response.end(new Message("Hello, World!").toJson(), NULL_HANDLER); } private void handleDb(HttpServerRequest req) { HttpServerResponse resp = req.response(); - SELECT_WORLD_QUERY.execute(Tuple.of(randomWorld()), res -> { + SELECT_WORLD_QUERY.execute(Tuple.of(boxedRandomWorldNumber()), res -> { if (res.succeeded()) { RowIterator resultSet = res.result().iterator(); if (!resultSet.hasNext()) { @@ -290,11 +288,12 @@ private void handleDb(HttpServerRequest req) { return; } Row row = resultSet.next(); - resp - .putHeader(HttpHeaders.SERVER, SERVER) - .putHeader(HttpHeaders.DATE, dateString) - .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(new World(row.getInteger(0), row.getInteger(1)).toBuffer(), NULL_HANDLER); + World word = new World(row.getInteger(0), row.getInteger(1)); + MultiMap headers = resp.headers(); + headers.add(HttpHeaders.SERVER, SERVER); + headers.add(HttpHeaders.DATE, dateString); + headers.add(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON); + resp.end(word.toJson(), NULL_HANDLER); } else { sendError(req, res.cause()); } @@ -304,10 +303,11 @@ private void handleDb(HttpServerRequest req) { class Queries implements Handler>> { boolean failed; - final JsonArray worlds; + final World[] worlds; final HttpServerRequest req; final HttpServerResponse resp; final int queries; + int worldsIndex; public Queries(HttpServerRequest req) { int queries = getQueries(req); @@ -315,13 +315,14 @@ public Queries(HttpServerRequest req) { this.req = req; this.resp = req.response(); this.queries = queries; - this.worlds = new JsonArray(new ArrayList<>(queries)); + this.worlds = new World[queries]; + this.worldsIndex = 0; } private void handle() { - client1.group(c -> { + client.group(c -> { for (int i = 0; i < queries; i++) { - c.preparedQuery(SELECT_WORLD).execute(Tuple.of(randomWorld()), this); + c.preparedQuery(SELECT_WORLD).execute(Tuple.of(boxedRandomWorldNumber()), this); } }); } @@ -337,50 +338,48 @@ public void handle(AsyncResult> ar) { // we need a final reference final Tuple row = ar.result().iterator().next(); - worlds.add(new JsonObject().put("id", row.getInteger(0)).put("randomNumber", row.getInteger(1))); + worlds[worldsIndex++] = new World(row.getInteger(0), row.getInteger(1)); // stop condition - if (worlds.size() == queries) { - resp - .putHeader(HttpHeaders.SERVER, SERVER) - .putHeader(HttpHeaders.DATE, dateString) - .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(worlds.toBuffer(), NULL_HANDLER); + if (worldsIndex == queries) { + MultiMap headers = resp.headers(); + headers.add(HttpHeaders.SERVER, SERVER); + headers.add(HttpHeaders.DATE, dateString); + headers.add(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON); + resp.end(World.toJson(worlds), NULL_HANDLER); } } } } - class Update { + private class Update { - final HttpServerRequest req; - boolean failed; - int queryCount; - final World[] worlds; + private final HttpServerRequest request; + private final World[] worldsToUpdate; + private boolean failed; + private int selectWorldCompletedCount; - public Update(HttpServerRequest req) { - final int queries = getQueries(req); - this.req = req; - this.worlds = new World[queries]; + public Update(HttpServerRequest request) { + this.request = request; + this.worldsToUpdate = new World[getQueries(request)]; } - private void handle() { - - client1.group(c -> { - PreparedQuery> preparedQuery = c.preparedQuery(SELECT_WORLD); - for (int i = 0; i < worlds.length; i++) { - int id = randomWorld(); - int index = i; - preparedQuery.execute(Tuple.of(id), ar2 -> { + public void handle() { + client.group(c -> { + final PreparedQuery> preparedQuery = c.preparedQuery(App.SELECT_WORLD); + for (int i = 0; i < worldsToUpdate.length; i++) { + final Integer id = boxedRandomWorldNumber(); + final int index = i; + preparedQuery.execute(Tuple.of(id), res -> { if (!failed) { - if (ar2.failed()) { + if (res.failed()) { failed = true; - sendError(req, ar2.cause()); + sendError(request, res.cause()); return; } - worlds[index] = new World(ar2.result().iterator().next().getInteger(0), randomWorld()); - if (++queryCount == worlds.length) { - handleUpdates(); + worldsToUpdate[index] = new World(res.result().iterator().next().getInteger(0), boxedRandomWorldNumber()); + if (++selectWorldCompletedCount == worldsToUpdate.length) { + randomWorldsQueryCompleted(); } } }); @@ -388,43 +387,32 @@ private void handle() { }); } - void handleUpdates() { - Arrays.sort(worlds); - int len = worlds.length; - if (0 < len && len <= AGGREGATED_UPDATE_WORLD_QUERY.length) { - List arguments = new ArrayList<>(); - for (World world : worlds) { - arguments.add(world.getId()); - arguments.add(world.getRandomNumber()); - } - Tuple tuple = Tuple.tuple(arguments); - PreparedQuery> query = AGGREGATED_UPDATE_WORLD_QUERY[len - 1]; - query.execute(tuple, this::sendResponse); - } else { - List batch = new ArrayList<>(); - for (World world : worlds) { - batch.add(Tuple.of(world.getRandomNumber(), world.getId())); - } - UPDATE_WORLD_QUERY.executeBatch(batch, this::sendResponse); + private void randomWorldsQueryCompleted() { + Arrays.sort(worldsToUpdate); + final List params = new ArrayList<>(worldsToUpdate.length * 2); + for (int i = 0, count = worldsToUpdate.length;i < count;i++) { + var world = worldsToUpdate[i]; + params.add(world.getId()); + params.add(world.getRandomNumber()); } + AGGREGATED_UPDATE_WORLD_QUERY[worldsToUpdate.length - 1].execute(Tuple.wrap(params), updateResult -> { + if (updateResult.failed()) { + sendError(request, updateResult.cause()); + return; + } + sendResponse(); + }); } - private void sendResponse(AsyncResult res) { - if (res.failed()) { - sendError(req, res.cause()); - return; - } - JsonArray json = new JsonArray(); - for (World world : worlds) { - json.add(world); - } - req.response() - .putHeader(HttpHeaders.SERVER, SERVER) - .putHeader(HttpHeaders.DATE, dateString) - .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON) - .end(json.toBuffer(), NULL_HANDLER); + private void sendResponse() { + var res = request.response(); + MultiMap headers = res.headers(); + headers.add(HttpHeaders.SERVER, App.SERVER); + headers.add(HttpHeaders.DATE, dateString); + headers.add(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_JSON); + Buffer buff = WorldJsonSerializer.toJsonBuffer(worldsToUpdate); + res.end(buff, null); } - } private void handleFortunes(HttpServerRequest req) { @@ -439,11 +427,12 @@ private void handleFortunes(HttpServerRequest req) { List fortunes = result.value(); fortunes.add(new Fortune(0, "Additional fortune added at request time.")); Collections.sort(fortunes); - response - .putHeader(HttpHeaders.SERVER, SERVER) - .putHeader(HttpHeaders.DATE, dateString) - .putHeader(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_HTML) - .end(FortunesTemplate.template(fortunes).render(factory).buffer(), NULL_HANDLER); + MultiMap headers = response.headers(); + headers.add(HttpHeaders.SERVER, SERVER); + headers.add(HttpHeaders.DATE, dateString); + headers.add(HttpHeaders.CONTENT_TYPE, RESPONSE_TYPE_HTML); + FortunesTemplate template = FortunesTemplate.template(fortunes); + response.end(template.render(factory).buffer(), NULL_HANDLER); } else { sendError(req, ar.cause()); } @@ -462,19 +451,17 @@ private void handleCaching(HttpServerRequest req) { count = Math.max(1, count); count = Math.min(500, count); List worlds = WORLD_CACHE.getCachedWorld(count); - JsonArray json = new JsonArray(worlds); HttpServerResponse response = req.response(); MultiMap headers = response.headers(); headers .add(HEADER_CONTENT_TYPE, RESPONSE_TYPE_JSON) .add(HEADER_SERVER, SERVER) .add(HEADER_DATE, dateString); - response.end(json.toBuffer(), NULL_HANDLER); + response.end(CachedWorld.toJson(worlds), NULL_HANDLER); } public static void main(String[] args) throws Exception { - - int eventLoopPoolSize = Runtime.getRuntime().availableProcessors(); + int eventLoopPoolSize = NUM_PROCESSORS; String sizeProp = System.getProperty("vertx.eventLoopPoolSize"); if (sizeProp != null) { try { @@ -522,6 +509,7 @@ private static void printConfig(Vertx vertx) { logger.error("Could not read Vertx version", e);; } logger.info("Vertx: " + version); + logger.info("Processors: " + NUM_PROCESSORS); logger.info("Event Loop Size: " + ((MultithreadEventExecutorGroup)vertx.nettyEventLoopGroup()).executorCount()); logger.info("Native transport : " + nativeTransport); logger.info("Transport : " + transport); diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java b/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java index f27e8805f33..423d5273f62 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/CachedWorld.java @@ -1,13 +1,17 @@ package vertx.model; -import io.vertx.core.json.JsonObject; +import com.julienviet.jsonsergen.JsonSerGen; +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.buffer.Buffer; -import java.util.Map; +import java.util.List; /** * The model for the "world" database table. */ -public final class CachedWorld extends JsonObject implements Comparable { +@DataObject +@JsonSerGen +public final class CachedWorld implements Comparable { private final int id; private final int randomNumber; @@ -19,7 +23,6 @@ public final class CachedWorld extends JsonObject implements Comparable worlds) { + return CachedWorldJsonSerializer.toJsonBuffer(worlds); + } } \ No newline at end of file diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/Fortune.java b/frameworks/Java/vertx/src/main/java/vertx/model/Fortune.java index d1df6fcfa1a..eb21f93feee 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/Fortune.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/Fortune.java @@ -7,11 +7,14 @@ /** * The model for the "fortune" database table. */ -public final class Fortune extends JsonObject implements Comparable { +public final class Fortune implements Comparable { private static final String ID = "id"; private static final String MESSAGE = "message"; + private final int id; + private final String message; + /** * Constructs a new fortune object with the given parameters. * @@ -19,20 +22,16 @@ public final class Fortune extends JsonObject implements Comparable { * @param message the message of the fortune */ public Fortune(int id, String message) { - put(ID, id); - put(MESSAGE, message); - } - - public Fortune(JsonObject doc) { - super(doc == null ? Collections.emptyMap() : doc.getMap()); + this.id = id; + this.message = message; } public int getId() { - return getInteger(ID); + return id; } public String getMessage() { - return getString(MESSAGE); + return message; } @Override diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/Message.java b/frameworks/Java/vertx/src/main/java/vertx/model/Message.java index 0fe3274afe0..ce240bd5ae9 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/Message.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/Message.java @@ -1,16 +1,29 @@ package vertx.model; -import io.vertx.core.json.JsonObject; +import com.julienviet.jsonsergen.JsonSerGen; +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.buffer.Buffer; -public class Message extends JsonObject { +@DataObject +@JsonSerGen +public class Message { - private static final String MESSAGE = "message"; + private String message; public Message(String message) { - put(MESSAGE, message); + this.message = message; } public String getMessage() { - return getString(MESSAGE); + return message; + } + + public Message setMessage(String message) { + this.message = message; + return this; + } + + public Buffer toJson() { + return MessageJsonSerializer.toJsonBuffer(this); } } diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/World.java b/frameworks/Java/vertx/src/main/java/vertx/model/World.java index 86f4d29e99b..43f7bfc2a61 100644 --- a/frameworks/Java/vertx/src/main/java/vertx/model/World.java +++ b/frameworks/Java/vertx/src/main/java/vertx/model/World.java @@ -1,13 +1,15 @@ package vertx.model; -import io.vertx.core.json.JsonObject; - -import java.util.Map; +import com.julienviet.jsonsergen.JsonSerGen; +import io.vertx.codegen.annotations.DataObject; +import io.vertx.core.buffer.Buffer; /** * The model for the "world" database table. */ -public final class World extends JsonObject implements Comparable { +@DataObject +@JsonSerGen +public final class World implements Comparable { private final int id; private final int randomNumber; @@ -19,7 +21,6 @@ public final class World extends JsonObject implements Comparable { * @param randomNumber the random number of the world */ public World(int id, int randomNumber) { - super(Map.of("id", id, "randomNumber", randomNumber)); this.id = id; this.randomNumber = randomNumber; } @@ -36,4 +37,12 @@ public int getRandomNumber() { public int compareTo(World o) { return Integer.compare(id, o.id); } + + public Buffer toJson() { + return WorldJsonSerializer.toJsonBuffer(this); + } + + public static Buffer toJson(World[] worlds) { + return WorldJsonSerializer.toJsonBuffer(worlds); + } } \ No newline at end of file diff --git a/frameworks/Java/vertx/src/main/java/vertx/model/package-info.java b/frameworks/Java/vertx/src/main/java/vertx/model/package-info.java new file mode 100644 index 00000000000..d0dfa9d492c --- /dev/null +++ b/frameworks/Java/vertx/src/main/java/vertx/model/package-info.java @@ -0,0 +1,4 @@ +@ModuleGen(name = "benchmark", groupPackage = "vertx.model") +package vertx.model; + +import io.vertx.codegen.annotations.ModuleGen; \ No newline at end of file diff --git a/frameworks/Java/vertx/vertx-postgres.dockerfile b/frameworks/Java/vertx/vertx-postgres.dockerfile index 3072a3ad381..dec7fa545a3 100644 --- a/frameworks/Java/vertx/vertx-postgres.dockerfile +++ b/frameworks/Java/vertx/vertx-postgres.dockerfile @@ -14,6 +14,7 @@ CMD export DBIP=`getent hosts tfb-database | awk '{ print $1 }'` && \ -server \ -XX:+UseNUMA \ -XX:+UseParallelGC \ + -Djava.lang.Integer.IntegerCache.high=10000 \ -Dvertx.disableMetrics=true \ -Dvertx.disableH2c=true \ -Dvertx.disableWebsockets=true \ diff --git a/frameworks/Java/vertx/vertx.dockerfile b/frameworks/Java/vertx/vertx.dockerfile index cfd269e37ae..2fe2a27a2c2 100644 --- a/frameworks/Java/vertx/vertx.dockerfile +++ b/frameworks/Java/vertx/vertx.dockerfile @@ -6,4 +6,4 @@ RUN mvn package -q EXPOSE 8080 -CMD ["java", "-Xms2G", "-Xmx2G", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dvertx.disableHttpHeadersValidation=true", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-jar", "target/vertx.benchmark-0.0.1-SNAPSHOT-fat.jar", "src/main/conf/config.json"] +CMD ["java", "-Xms2G", "-Xmx2G", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-Djava.lang.Integer.IntegerCache.high=10000", "-Dvertx.disableMetrics=true", "-Dvertx.disableH2c=true", "-Dvertx.disableWebsockets=true", "-Dvertx.flashPolicyHandler=false", "-Dvertx.threadChecks=false", "-Dvertx.disableContextTimings=true", "-Dvertx.disableTCCL=true", "-Dvertx.disableHttpHeadersValidation=true", "-Dio.netty.buffer.checkBounds=false", "-Dio.netty.buffer.checkAccessible=false", "-jar", "target/vertx.benchmark-0.0.1-SNAPSHOT-fat.jar", "src/main/conf/config.json"] From 57f2f117488029a625feea0605f7da76bfb2a0b9 Mon Sep 17 00:00:00 2001 From: Anton Kirilov Date: Fri, 26 Jul 2024 17:50:09 +0100 Subject: [PATCH 50/62] H2O: Use 2 database connections per thread again (#9176) --- frameworks/C/h2o/h2o.dockerfile | 2 +- frameworks/C/h2o/src/handlers/world.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/C/h2o/h2o.dockerfile b/frameworks/C/h2o/h2o.dockerfile index cfabc77bb3b..bca0d12b19e 100644 --- a/frameworks/C/h2o/h2o.dockerfile +++ b/frameworks/C/h2o/h2o.dockerfile @@ -109,4 +109,4 @@ CMD ["taskset", \ "dbname=hello_world host=tfb-database password=benchmarkdbpass sslmode=disable user=benchmarkdbuser", \ "-f", \ "/opt/h2o_app/share/h2o_app/template", \ - "-m1"] + "-m2"] diff --git a/frameworks/C/h2o/src/handlers/world.c b/frameworks/C/h2o/src/handlers/world.c index a87ee4c4282..82d29ce08b8 100644 --- a/frameworks/C/h2o/src/handlers/world.c +++ b/frameworks/C/h2o/src/handlers/world.c @@ -237,9 +237,9 @@ static int do_multiple_queries(bool do_update, bool use_cache, h2o_req_t *req) const size_t num_query = get_query_number(req); - // MAX_QUERIES is a relatively small number, so assume no overflow in the following - // arithmetic operations. - assert(num_query && num_query <= MAX_QUERIES); + // MAX_QUERIES is a relatively small number, say less than or equal to UINT16_MAX, so assume no + // overflow in the following arithmetic operations. + assert(num_query && num_query <= MAX_QUERIES && num_query <= UINT16_MAX); size_t base_size = offsetof(multiple_query_ctx_t, res) + num_query * sizeof(query_result_t); @@ -373,7 +373,7 @@ static void do_updates(multiple_query_ctx_t *query_ctx) for (size_t i = 0; i < query_ctx->num_result; i++) { query_ctx->res[i].id = htonl(query_ctx->res[i].id); query_ctx->res[i].random_number = - htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed)); + htonl(1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed)); paramFormats[2 * i] = 1; paramFormats[2 * i + 1] = 1; paramLengths[2 * i] = sizeof(query_ctx->res[i].id); From f2a87b60800fac06a293cc5e1270a78e8cba05d0 Mon Sep 17 00:00:00 2001 From: Joan Miquel Date: Mon, 29 Jul 2024 23:14:27 +0200 Subject: [PATCH 51/62] [php] Fix Swoole and faster docker builds (#9169) * Fix Symfony Swoole * Fix Laravel Swoole * Fix Simps Swoole * Fix Laravel Laravels Swoole variant * Fix Lumen Swoole variants * Fix MixPHP Swoole * Fix Ubiquity Swoole variants --- .../PHP/laravel/laravel-laravel-s.dockerfile | 18 ++++-------- .../PHP/laravel/laravel-swoole.dockerfile | 20 ++++--------- .../PHP/lumen/lumen-laravel-s.dockerfile | 15 +++------- frameworks/PHP/lumen/lumen-swoole.dockerfile | 29 +++++-------------- .../PHP/mixphp/mixphp-swoole-mysql.dockerfile | 18 ++++-------- frameworks/PHP/simps/simps-micro.dockerfile | 17 ++++------- frameworks/PHP/simps/simps.dockerfile | 17 ++++------- frameworks/PHP/symfony/public/swoole.php | 2 +- .../PHP/symfony/symfony-swoole.dockerfile | 13 +++------ .../ubiquity/ubiquity-swoole-mysql.dockerfile | 24 ++++----------- .../PHP/ubiquity/ubiquity-swoole.dockerfile | 22 ++++---------- 11 files changed, 53 insertions(+), 142 deletions(-) diff --git a/frameworks/PHP/laravel/laravel-laravel-s.dockerfile b/frameworks/PHP/laravel/laravel-laravel-s.dockerfile index 4cce4090f3d..a0e946e5097 100644 --- a/frameworks/PHP/laravel/laravel-laravel-s.dockerfile +++ b/frameworks/PHP/laravel/laravel-laravel-s.dockerfile @@ -1,25 +1,17 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole -RUN docker-php-ext-install pdo_mysql pcntl opcache > /dev/null +RUN docker-php-ext-install pcntl opcache curl > /dev/null RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit_buffer_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini -ADD ./ /laravel WORKDIR /laravel +COPY --link . . RUN mkdir -p /laravel/bootstrap/cache /laravel/storage/logs /laravel/storage/framework/sessions /laravel/storage/framework/views /laravel/storage/framework/cache -RUN chmod -R 777 /laravel -RUN apt-get update > /dev/null && \ - apt-get install -yqq git unzip > /dev/null -RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" -RUN mv composer.phar /usr/local/bin/composer - -COPY deploy/laravel-s/composer.json ./ +COPY --link deploy/laravel-s/composer.json . RUN echo "LARAVELS_LISTEN_IP=0.0.0.0" >> .env RUN echo "LARAVELS_LISTEN_PORT=8080" >> .env @@ -30,4 +22,4 @@ RUN php artisan laravels publish EXPOSE 8080 -CMD php bin/laravels start +ENTRYPOINT [ "php", "bin/laravels", "start" ] diff --git a/frameworks/PHP/laravel/laravel-swoole.dockerfile b/frameworks/PHP/laravel/laravel-swoole.dockerfile index 77cfef19fe0..3882a7ac4c8 100644 --- a/frameworks/PHP/laravel/laravel-swoole.dockerfile +++ b/frameworks/PHP/laravel/laravel-swoole.dockerfile @@ -1,33 +1,23 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole -RUN docker-php-ext-install pdo_mysql pcntl opcache > /dev/null +RUN docker-php-ext-install pcntl opcache curl > /dev/null RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini RUN echo "opcache.jit_buffer_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini -ADD ./ /laravel WORKDIR /laravel +COPY --link . . RUN mkdir -p /laravel/bootstrap/cache /laravel/storage/framework/sessions /laravel/storage/framework/views /laravel/storage/framework/cache -RUN chmod -R 777 /laravel -RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git unzip > /dev/null - -RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" -RUN mv composer.phar /usr/local/bin/composer - -COPY deploy/swoole/composer.json ./ +COPY --link deploy/swoole/composer.json . RUN echo "APP_SWOOLE=true" >> .env RUN composer install -a --no-dev --quiet RUN php artisan optimize - EXPOSE 8080 -CMD php artisan swoole:http start +ENTRYPOINT [ "php", "artisan", "swoole:http", "start" ] diff --git a/frameworks/PHP/lumen/lumen-laravel-s.dockerfile b/frameworks/PHP/lumen/lumen-laravel-s.dockerfile index a8a0aebd68a..a2b4be68310 100644 --- a/frameworks/PHP/lumen/lumen-laravel-s.dockerfile +++ b/frameworks/PHP/lumen/lumen-laravel-s.dockerfile @@ -1,24 +1,17 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole -RUN docker-php-ext-install pdo_mysql pcntl opcache > /dev/null +RUN docker-php-ext-install pcntl opcache curl > /dev/null RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini #RUN echo "opcache.jit=1205" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini #RUN echo "opcache.jit_buffer_size=128M" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini -ADD ./ /lumen WORKDIR /lumen +ADD --link . . RUN mkdir -p /lumen/bootstrap/cache /lumen/storage/logs /lumen/storage/framework/sessions /lumen/storage/framework/views /lumen/storage/framework/cache RUN chmod -R 777 /lumen -RUN apt-get update > /dev/null && \ - apt-get install -yqq git unzip > /dev/null -RUN php -r "copy('https://install.phpcomposer.com/installer', 'composer-setup.php');" && php composer-setup.php && php -r "unlink('composer-setup.php');" -RUN mv composer.phar /usr/local/bin/composer - COPY deploy/laravel-s/composer.json ./ RUN echo "LARAVELS_LISTEN_IP=0.0.0.0" >> .env @@ -29,4 +22,4 @@ RUN php artisan laravels publish EXPOSE 8080 -CMD php bin/laravels start +ENTRYPOINT [ "php", "bin/laravels", "start" ] diff --git a/frameworks/PHP/lumen/lumen-swoole.dockerfile b/frameworks/PHP/lumen/lumen-swoole.dockerfile index 3e4c866c031..de3d4294973 100644 --- a/frameworks/PHP/lumen/lumen-swoole.dockerfile +++ b/frameworks/PHP/lumen/lumen-swoole.dockerfile @@ -1,31 +1,16 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole +RUN docker-php-ext-install pcntl opcache curl > /dev/null -RUN docker-php-ext-install pdo_mysql > /dev/null - -ADD ./ /lumen WORKDIR /lumen -COPY deploy/swoole/php.ini /usr/local/etc/php/ - -RUN mkdir -p /lumen/storage/framework/sessions -RUN mkdir -p /lumen/storage/framework/views -RUN mkdir -p /lumen/storage/framework/cache - -RUN chmod -R 777 /lumen +ADD --link . . -# Install composer using the installation method documented at https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md -# This method was chosen because composer is not part of the apt repositories that are in the default PHP 7.2 docker image -# Adding alternate apt php repos can potentially cause problems with extension compatibility between the php build from the docker image and the alternate php build -# An additional benefit of this method is that the correct version of composer will be used for the environment and version of the php system in the docker image -RUN deploy/swoole/install-composer.sh +COPY --link deploy/swoole/php.ini /usr/local/etc/php/ -RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git unzip > /dev/null +RUN mkdir -p /lumen/storage/framework/sessions /lumen/storage/framework/views /lumen/storage/framework/cache COPY deploy/swoole/composer* ./ -RUN php composer.phar install --optimize-autoloader --classmap-authoritative --no-dev --quiet +RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN echo "APP_SWOOLE=true" >> .env @@ -33,4 +18,4 @@ RUN chmod -R 777 /lumen EXPOSE 8080 -CMD php artisan swoole:http start +ENTRYPOINT [ "php", "artisan", "swoole:http", "start" ] diff --git a/frameworks/PHP/mixphp/mixphp-swoole-mysql.dockerfile b/frameworks/PHP/mixphp/mixphp-swoole-mysql.dockerfile index 2001b9fde1d..846a3b88a87 100644 --- a/frameworks/PHP/mixphp/mixphp-swoole-mysql.dockerfile +++ b/frameworks/PHP/mixphp/mixphp-swoole-mysql.dockerfile @@ -1,13 +1,10 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && docker-php-ext-enable swoole +RUN docker-php-ext-install pcntl opcache bcmath > /dev/null -RUN docker-php-ext-install opcache pdo_mysql bcmath > /dev/null - -RUN apt -yqq update && apt -yqq install git unzip > /dev/null - -COPY . /mixphp -COPY php.ini /usr/local/etc/php/ +WORKDIR /mixphp +COPY --link . . +COPY --link php.ini /usr/local/etc/php/ RUN echo "opcache.enable=1" >> /usr/local/etc/php/php.ini RUN echo "opcache.enable_cli=1" >> /usr/local/etc/php/php.ini RUN echo "pcre.jit=1" >> /usr/local/etc/php/php.ini @@ -16,9 +13,6 @@ RUN echo "opcache.jit_buffer_size=256M" >> /usr/local/etc/php/php.ini RUN php -v && php -i | grep opcache -WORKDIR /mixphp - -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer RUN composer install --no-dev --classmap-authoritative --quiet > /dev/null RUN composer dumpautoload -o @@ -27,4 +21,4 @@ RUN chmod -R 777 /mixphp/runtime/logs EXPOSE 9501 -CMD php /mixphp/bin/swoole.php start +ENTRYPOINT [ "php", "/mixphp/bin/swoole.php", "start" ] diff --git a/frameworks/PHP/simps/simps-micro.dockerfile b/frameworks/PHP/simps/simps-micro.dockerfile index baa74e103e1..4e5b9ffd075 100644 --- a/frameworks/PHP/simps/simps-micro.dockerfile +++ b/frameworks/PHP/simps/simps-micro.dockerfile @@ -1,22 +1,15 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole - -RUN docker-php-ext-install opcache pdo_mysql > /dev/null - -RUN apt -yqq update > /dev/null && \ - apt -yqq install git unzip > /dev/null +RUN docker-php-ext-install pcntl opcache curl > /dev/null WORKDIR /simps -COPY . /simps -COPY php.ini /usr/local/etc/php/ +COPY --link . . +COPY --link php.ini /usr/local/etc/php/ -RUN curl -sSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer install --no-dev --classmap-authoritative --quiet > /dev/null RUN composer dumpautoload -o EXPOSE 8080 -CMD php sbin/simps.php http:start +ENTRYPOINT [ "php", "sbin/simps.php", "http:start" ] diff --git a/frameworks/PHP/simps/simps.dockerfile b/frameworks/PHP/simps/simps.dockerfile index baa74e103e1..4e5b9ffd075 100644 --- a/frameworks/PHP/simps/simps.dockerfile +++ b/frameworks/PHP/simps/simps.dockerfile @@ -1,22 +1,15 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole - -RUN docker-php-ext-install opcache pdo_mysql > /dev/null - -RUN apt -yqq update > /dev/null && \ - apt -yqq install git unzip > /dev/null +RUN docker-php-ext-install pcntl opcache curl > /dev/null WORKDIR /simps -COPY . /simps -COPY php.ini /usr/local/etc/php/ +COPY --link . . +COPY --link php.ini /usr/local/etc/php/ -RUN curl -sSL https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer RUN composer install --no-dev --classmap-authoritative --quiet > /dev/null RUN composer dumpautoload -o EXPOSE 8080 -CMD php sbin/simps.php http:start +ENTRYPOINT [ "php", "sbin/simps.php", "http:start" ] diff --git a/frameworks/PHP/symfony/public/swoole.php b/frameworks/PHP/symfony/public/swoole.php index 2c0695003f4..a1825fc344e 100644 --- a/frameworks/PHP/symfony/public/swoole.php +++ b/frameworks/PHP/symfony/public/swoole.php @@ -15,6 +15,6 @@ require_once dirname(__DIR__).'/vendor/autoload_runtime.php'; -return function (array $context) { +return function (array $context): Kernel { return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']); }; diff --git a/frameworks/PHP/symfony/symfony-swoole.dockerfile b/frameworks/PHP/symfony/symfony-swoole.dockerfile index 37403a24c97..e8fda091bb3 100644 --- a/frameworks/PHP/symfony/symfony-swoole.dockerfile +++ b/frameworks/PHP/symfony/symfony-swoole.dockerfile @@ -1,16 +1,11 @@ -FROM php:8.3-cli - -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole - -RUN pecl install apcu > /dev/null && \ - docker-php-ext-enable apcu +FROM phpswoole/swoole:5.1.3-php8.3 RUN apt-get update -yqq && \ - apt-get install -yqq libpq-dev libicu-dev git unzip > /dev/null && \ + apt-get install -yqq libpq-dev libicu-dev > /dev/null && \ docker-php-ext-install pdo_pgsql opcache intl > /dev/null -COPY --from=composer/composer:latest-bin --link /composer /usr/local/bin/composer +RUN pecl install apcu > /dev/null && \ + docker-php-ext-enable apcu COPY --link deploy/swoole/php.ini /usr/local/etc/php/ WORKDIR /symfony diff --git a/frameworks/PHP/ubiquity/ubiquity-swoole-mysql.dockerfile b/frameworks/PHP/ubiquity/ubiquity-swoole-mysql.dockerfile index d4195a1d945..7a99706faaf 100644 --- a/frameworks/PHP/ubiquity/ubiquity-swoole-mysql.dockerfile +++ b/frameworks/PHP/ubiquity/ubiquity-swoole-mysql.dockerfile @@ -1,29 +1,17 @@ -FROM php:8.3-cli +FROM phpswoole/swoole:5.1.3-php8.3 -RUN apt-get update > /dev/null - -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole - -RUN docker-php-ext-install pdo_mysql opcache pcntl > /dev/null +RUN docker-php-ext-install pcntl opcache > /dev/null COPY deploy/conf/php-async.ini /usr/local/etc/php/php.ini -ADD ./ /ubiquity WORKDIR /ubiquity +ADD --link . . RUN chmod -R 777 /ubiquity -RUN ["chmod", "+x", "deploy/run/install-composer.sh"] - -RUN deploy/run/install-composer.sh - -RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git unzip > /dev/null - -RUN php composer.phar require phpmv/ubiquity-devtools:dev-master phpmv/ubiquity-swoole:dev-master --quiet +RUN composer require phpmv/ubiquity-devtools:dev-master phpmv/ubiquity-swoole:dev-master --quiet -RUN php composer.phar install --optimize-autoloader --classmap-authoritative --no-dev --quiet +RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN chmod 777 -R /ubiquity/.ubiquity/* @@ -36,4 +24,4 @@ COPY deploy/conf/swoole/mysql/swooleServices.php app/config/swooleServices.php EXPOSE 8080 -CMD /ubiquity/vendor/bin/Ubiquity serve -t=swoole -p=8080 -h=0.0.0.0 +ENTRYPOINT [ "/ubiquity/vendor/bin/Ubiquity", "serve", "-t=swoole", "-p=8080", "-h=0.0.0.0" ] diff --git a/frameworks/PHP/ubiquity/ubiquity-swoole.dockerfile b/frameworks/PHP/ubiquity/ubiquity-swoole.dockerfile index ff57c3c54e1..d4807c4a8ad 100644 --- a/frameworks/PHP/ubiquity/ubiquity-swoole.dockerfile +++ b/frameworks/PHP/ubiquity/ubiquity-swoole.dockerfile @@ -1,9 +1,4 @@ -FROM php:8.3-cli - -RUN apt-get update > /dev/null - -RUN pecl install swoole > /dev/null && \ - docker-php-ext-enable swoole +FROM phpswoole/swoole:5.1.3-php8.3 RUN apt-get install -y libpq-dev \ && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ @@ -11,21 +6,14 @@ RUN apt-get install -y libpq-dev \ COPY deploy/conf/php-async.ini /usr/local/etc/php/php.ini -ADD ./ /ubiquity WORKDIR /ubiquity +ADD --link . . RUN chmod -R 777 /ubiquity -RUN ["chmod", "+x", "deploy/run/install-composer.sh"] - -RUN deploy/run/install-composer.sh - -RUN apt-get update -yqq > /dev/null && \ - apt-get install -yqq git unzip > /dev/null - -RUN php composer.phar require phpmv/ubiquity-devtools:dev-master phpmv/ubiquity-swoole:dev-master --quiet +RUN composer require phpmv/ubiquity-devtools:dev-master phpmv/ubiquity-swoole:dev-master --quiet -RUN php composer.phar install --optimize-autoloader --classmap-authoritative --no-dev --quiet +RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN chmod 777 -R /ubiquity/.ubiquity/* @@ -38,4 +26,4 @@ COPY deploy/conf/swoole/pgsql/swooleServices.php app/config/swooleServices.php EXPOSE 8080 -CMD /ubiquity/vendor/bin/Ubiquity serve -t=swoole -p=8080 -h=0.0.0.0 +ENTRYPOINT [ "/ubiquity/vendor/bin/Ubiquity", "serve", "-t=swoole", "-p=8080", "-h=0.0.0.0" ] From 723dd6eeb2dc6a8c9e3d8f2f24f0b5c17acb39e6 Mon Sep 17 00:00:00 2001 From: Joan Miquel Date: Wed, 31 Jul 2024 20:19:05 +0200 Subject: [PATCH 52/62] Update to MySQL 9.0 (#9183) --- toolset/databases/mysql/create.sql | 6 +++--- toolset/databases/mysql/my.cnf | 2 +- toolset/databases/mysql/mysql.dockerfile | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/toolset/databases/mysql/create.sql b/toolset/databases/mysql/create.sql index 94cb995deb3..d97fb37f490 100644 --- a/toolset/databases/mysql/create.sql +++ b/toolset/databases/mysql/create.sql @@ -2,14 +2,14 @@ # http://stackoverflow.com/questions/37719818/the-server-time-zone-value-aest-is-unrecognized-or-represents-more-than-one-ti SET GLOBAL time_zone = '+00:00'; -CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'%' IDENTIFIED WITH mysql_native_password BY 'benchmarkdbpass'; -CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'benchmarkdbpass'; +CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'%' IDENTIFIED WITH caching_sha2_password BY 'benchmarkdbpass'; +CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'benchmarkdbpass'; -- GitHub Actions/CI run the database server on the same system as the benchmarks. -- Because we setup MySQL with the skip-name-resolve option, the IP address 127.0.0.1 might not be resolved to localhost -- anymore. This does not seem to matter, as long as Unix sockets are being used (e.g. when setting up the docker image), -- because the host is set to be localhost implicitly, but it matters for local TCP connections. -CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'127.0.0.1' IDENTIFIED WITH mysql_native_password BY 'benchmarkdbpass'; +CREATE USER IF NOT EXISTS 'benchmarkdbuser'@'127.0.0.1' IDENTIFIED WITH caching_sha2_password BY 'benchmarkdbpass'; # modified from SO answer http://stackoverflow.com/questions/5125096/for-loop-in-mysql CREATE DATABASE IF NOT EXISTS hello_world; diff --git a/toolset/databases/mysql/my.cnf b/toolset/databases/mysql/my.cnf index 40ffa8dd9eb..e1a401ae2d9 100644 --- a/toolset/databases/mysql/my.cnf +++ b/toolset/databases/mysql/my.cnf @@ -16,7 +16,7 @@ default-character-set=utf8 # * Basic Settings # default-storage-engine = innodb -mysql_native_password = ON +#mysql_native_password = ON # disabled in v9 #default_authentication_plugin = mysql_native_password user = mysql diff --git a/toolset/databases/mysql/mysql.dockerfile b/toolset/databases/mysql/mysql.dockerfile index 1aae5eb7d38..b5c5b6a67bb 100644 --- a/toolset/databases/mysql/mysql.dockerfile +++ b/toolset/databases/mysql/mysql.dockerfile @@ -1,4 +1,4 @@ -FROM mysql:8.4 +FROM mysql:9.0 ENV MYSQL_ROOT_PASSWORD=root ENV MYSQL_USER=benchmarkdbuser From 31599d26230c61f5d15714fea01447d7926a8529 Mon Sep 17 00:00:00 2001 From: Joan Miquel Date: Wed, 31 Jul 2024 20:19:18 +0200 Subject: [PATCH 53/62] Fix Nodejs mysql-raw.js (#9184) --- frameworks/JavaScript/nodejs/handlers/mysql-raw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/nodejs/handlers/mysql-raw.js b/frameworks/JavaScript/nodejs/handlers/mysql-raw.js index 5fa1ea3c625..6063b4020e4 100644 --- a/frameworks/JavaScript/nodejs/handlers/mysql-raw.js +++ b/frameworks/JavaScript/nodejs/handlers/mysql-raw.js @@ -1,6 +1,6 @@ const h = require('../helper'); const async = require('async'); -const mysql = require('mysql'); +const mysql = require('mysql2'); const connection = mysql.createConnection({ host: 'tfb-database', user: 'benchmarkdbuser', From 536f6cfea5d91808e81276592ba602c477f41f97 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Wed, 31 Jul 2024 20:19:28 +0200 Subject: [PATCH 54/62] ntex: Upgrade to ntex-2.0 (#9185) --- frameworks/Rust/ntex/Cargo.toml | 11 +++++----- frameworks/Rust/ntex/src/db.rs | 31 +++++++++++++++------------- frameworks/Rust/ntex/src/main_plt.rs | 2 +- frameworks/Rust/ntex/src/utils.rs | 5 ++--- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/frameworks/Rust/ntex/Cargo.toml b/frameworks/Rust/ntex/Cargo.toml index b1aff0f6435..6699c6c0f1d 100755 --- a/frameworks/Rust/ntex/Cargo.toml +++ b/frameworks/Rust/ntex/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ntex" -version = "1.0.0" +version = "2.0.0" edition = "2018" [[bin]] @@ -37,22 +37,23 @@ tokio = ["ntex/tokio"] async-std = ["ntex/async-std"] [dependencies] -ntex = "1.0.0" +ntex = "=2.0.3" ntex-bytes = { version = "0.1.21", features=["simd"] } mimalloc = { version = "0.1.25", default-features = false } snmalloc-rs = { version = "0.3.3", features = ["native-cpu"] } yarte = { version = "0.15", features = ["bytes-buf", "json"] } buf-min = { version = "0.7", features = ["ntex-bytes"] } -env_logger = "0.10" +env_logger = "0.11" nanorand = { version = "0.7", default-features = false, features = ["std", "wyrand", "tls"] } atoi = "2.0" num_cpus = "1.16" -smallvec = "1.11" +smallvec = "1.13" +futures = "0.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" log = { version = "0.4", features = ["release_max_level_off"] } tok_io = {version = "1", package = "tokio" } -tokio-postgres = { git="https://github.com/fafhrd91/postgres.git", branch="ntex-1.0" } +tokio-postgres = { git="https://github.com/fafhrd91/postgres.git", branch="ntex-2" } [profile.release] opt-level = 3 diff --git a/frameworks/Rust/ntex/src/db.rs b/frameworks/Rust/ntex/src/db.rs index 578465a90e2..5bceed5b73e 100644 --- a/frameworks/Rust/ntex/src/db.rs +++ b/frameworks/Rust/ntex/src/db.rs @@ -1,10 +1,11 @@ use std::{cell::RefCell, fmt::Write as FmtWrite}; +use futures::stream::{futures_unordered::FuturesUnordered, StreamExt}; use nanorand::{Rng, WyRand}; use ntex::util::{BufMut, Bytes, BytesMut}; use smallvec::SmallVec; use tokio_postgres::types::ToSql; -use tokio_postgres::{connect, Client, Statement}; +use tokio_postgres::{connect, Client, Row, Statement}; use yarte::{ywrite_html, Serialize}; use super::utils; @@ -82,7 +83,7 @@ impl PgConnection { let row = self.cl.query_one(&self.world, &[&random_id]).await.unwrap(); let mut body = self.buf.borrow_mut(); - utils::reserve(&mut body); + utils::reserve(&mut body, 256); World { id: row.get(0), randomnumber: row.get(1), @@ -91,17 +92,20 @@ impl PgConnection { body.split().freeze() } + async fn get_one_world(&self, id: i32) -> Row { + self.cl.query_one(&self.world, &[&id]).await.unwrap() + } + pub async fn get_worlds(&self, num: usize) -> Bytes { let mut rng = self.rng.clone(); - let mut queries = SmallVec::<[_; 32]>::new(); + let mut queries = FuturesUnordered::new(); (0..num).for_each(|_| { let w_id = (rng.generate::() % 10_000 + 1) as i32; - queries.push(self.cl.query_one(&self.world, &[&w_id])); + queries.push(self.get_one_world(w_id)) }); let mut worlds = SmallVec::<[_; 32]>::new(); - for fut in queries { - let row = fut.await.unwrap(); + while let Some(row) = queries.next().await { worlds.push(World { id: row.get(0), randomnumber: row.get(1), @@ -109,7 +113,7 @@ impl PgConnection { } let mut body = self.buf.borrow_mut(); - utils::reserve(&mut body); + utils::reserve(&mut body, 8 * 1024); body.put_u8(b'['); worlds.iter().for_each(|w| { w.to_bytes_mut(&mut *body); @@ -121,16 +125,15 @@ impl PgConnection { } pub async fn update(&self, num: usize) -> Bytes { - let mut rng = nanorand::tls_rng(); - let mut queries = SmallVec::<[_; 32]>::new(); + let mut rng = self.rng.clone(); + let mut queries = FuturesUnordered::new(); (0..num).for_each(|_| { let w_id = (rng.generate::() % 10_000 + 1) as i32; - queries.push(self.cl.query_one(&self.world, &[&w_id])); + queries.push(self.get_one_world(w_id)) }); let mut worlds = SmallVec::<[_; 32]>::new(); - for fut in queries.into_iter() { - let row = fut.await.unwrap(); + while let Some(row) = queries.next().await { worlds.push(World { id: row.get(0), randomnumber: (rng.generate::() % 10_000 + 1) as i32, @@ -148,7 +151,7 @@ impl PgConnection { let _ = self.cl.query(&self.updates[num - 1], ¶ms).await; let mut body = self.buf.borrow_mut(); - utils::reserve(&mut body); + utils::reserve(&mut body, 8 * 1024); body.put_u8(b'['); worlds.iter().for_each(|w| { w.to_bytes_mut(&mut *body); @@ -174,7 +177,7 @@ impl PgConnection { fortunes.sort_by(|it, next| it.message.cmp(next.message)); let mut body = std::mem::replace(&mut *self.buf.borrow_mut(), BytesMut::new()); - utils::reserve(&mut body); + utils::reserve(&mut body, 8 * 1024); ywrite_html!(body, "{{> fortune }}"); let result = body.split().freeze(); let _ = std::mem::replace(&mut *self.buf.borrow_mut(), body); diff --git a/frameworks/Rust/ntex/src/main_plt.rs b/frameworks/Rust/ntex/src/main_plt.rs index 4e9279d4ebf..cda9b69fa15 100644 --- a/frameworks/Rust/ntex/src/main_plt.rs +++ b/frameworks/Rust/ntex/src/main_plt.rs @@ -35,7 +35,7 @@ impl Future for App { Ok((req, _)) => { let _ = this.io.with_write_buf(|buf| { buf.with_bytes_mut(|buf| { - utils::reserve(buf); + utils::reserve(buf, 2 * 1024); match req.path() { "/json" => { buf.extend_from_slice(JSON); diff --git a/frameworks/Rust/ntex/src/utils.rs b/frameworks/Rust/ntex/src/utils.rs index 5792506dd71..719d5962dd4 100644 --- a/frameworks/Rust/ntex/src/utils.rs +++ b/frameworks/Rust/ntex/src/utils.rs @@ -11,7 +11,6 @@ pub const HDR_HTML_CONTENT_TYPE: HeaderValue = HeaderValue::from_static("text/html; charset=utf-8"); pub const BODY_PLAIN_TEXT: Bytes = Bytes::from_static(b"Hello, World!"); -const LW: usize = 1024; const HW: usize = 128 * 1024; pub const SIZE: usize = 27; @@ -25,9 +24,9 @@ pub fn get_query_param(query: Option<&str>) -> usize { cmp::min(500, cmp::max(1, q) as usize) } -pub fn reserve(buf: &mut BytesMut) { +pub fn reserve(buf: &mut BytesMut, lw: usize) { let remaining = buf.remaining_mut(); - if remaining < LW { + if remaining < lw { buf.reserve(HW); } } From 2777f0a10cc787a64d7faedc51191d61426c48e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:20:13 +0000 Subject: [PATCH 55/62] Bump mysql2 from 3.9.7 to 3.9.8 in /frameworks/JavaScript/hapi Bumps [mysql2](https://github.com/sidorares/node-mysql2) from 3.9.7 to 3.9.8. - [Release notes](https://github.com/sidorares/node-mysql2/releases) - [Changelog](https://github.com/sidorares/node-mysql2/blob/master/Changelog.md) - [Commits](https://github.com/sidorares/node-mysql2/compare/v3.9.7...v3.9.8) --- updated-dependencies: - dependency-name: mysql2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/JavaScript/hapi/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/hapi/package.json b/frameworks/JavaScript/hapi/package.json index 5d6070a266a..6a6c23a897b 100644 --- a/frameworks/JavaScript/hapi/package.json +++ b/frameworks/JavaScript/hapi/package.json @@ -10,7 +10,7 @@ "handlebars": "4.3.0", "mongoose": "5.13.20", "mysql": "2.16.0", - "mysql2": "3.9.7", + "mysql2": "3.9.8", "pg": "8.5.1", "pg-hstore": "2.3.2", "sequelize": "6.29.0" From 7b0f9539052ca4d7becb9fcf56d2bb06c62c251f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:21:20 +0000 Subject: [PATCH 56/62] Bump fast-xml-parser and @aws-sdk/credential-providers Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and [@aws-sdk/credential-providers](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-providers). These dependencies needed to be updated together. Updates `fast-xml-parser` from 4.2.5 to 4.4.1 - [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases) - [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md) - [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.2.5...v4.4.1) Updates `@aws-sdk/credential-providers` from 3.398.0 to 3.621.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-providers/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.621.0/packages/credential-providers) --- updated-dependencies: - dependency-name: fast-xml-parser dependency-type: indirect - dependency-name: "@aws-sdk/credential-providers" dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .../JavaScript/spliffy/package-lock.json | 3541 ++++++++++++----- 1 file changed, 2581 insertions(+), 960 deletions(-) diff --git a/frameworks/JavaScript/spliffy/package-lock.json b/frameworks/JavaScript/spliffy/package-lock.json index 40b146ce31c..114cddc45d1 100644 --- a/frameworks/JavaScript/spliffy/package-lock.json +++ b/frameworks/JavaScript/spliffy/package-lock.json @@ -4,986 +4,2619 @@ "lockfileVersion": 1, "requires": true, "dependencies": { - "@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", - "optional": true, - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "@aws-sdk/client-sso-oidc": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.621.0.tgz", + "integrity": "sha512-mMjk3mFUwV2Y68POf1BQMTF+F6qxt5tPu6daEUCNGC9Cenk3h2YXQQoS4/eSyYzuBiYk3vx49VgleRvdvkg8rg==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-sdk/client-sso": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", + "requires": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.621.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", + "requires": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.621.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", + "requires": { + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", + "integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/token-providers": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz", + "integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/config-resolver": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/credential-provider-imds": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", + "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/hash-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/invalid-dependency": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-content-length": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", + "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "requires": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-retry": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + } + }, + "@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "requires": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "requires": { + "@smithy/types": "^3.3.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "requires": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-node": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", + "requires": { + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "requires": { + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "requires": { + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" } } }, - "@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "optional": true, - "requires": { - "tslib": "^1.11.1" + "@aws-sdk/core": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.621.0.tgz", + "integrity": "sha512-CtOwWmDdEiINkGXD93iGfXjN0WmCp9l45cDWHHGa8lRgEDyhuL7bwd/pH5aSzj0j8SiQBG2k0S7DHbd5RaqvbQ==", + "requires": { + "@smithy/core": "^2.3.1", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" }, "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true + "@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "requires": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "requires": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/signature-v4": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.0.tgz", + "integrity": "sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "requires": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "requires": { + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "requires": { + "strnum": "^1.0.5" + } } } }, - "@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", - "optional": true, - "requires": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@aws-sdk/credential-provider-http": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.621.0.tgz", + "integrity": "sha512-/jc2tEsdkT1QQAI5Dvoci50DbSxtJrevemwFsm0B73pwCcOQZ5ZwwSdVqGsPutzYzUVx3bcXg3LRL7jLACqRIg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" }, "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true - } - } - }, - "@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", - "optional": true, - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true - } - } - }, - "@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", - "optional": true, - "requires": { - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true - } - } - }, - "@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "optional": true, - "requires": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "optional": true + "@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "requires": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "requires": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "requires": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "requires": { + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + } } } }, - "@aws-sdk/client-cognito-identity": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.398.0.tgz", - "integrity": "sha512-Pr/S1f8R2FsJ8DwBC6g0CSdtZNNV5dMHhlIi+t8YAmCJvP4KT+UhzFjbvQRINlBRLFuGUuP7p5vRcGVELD3+wA==", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.398.0", - "@aws-sdk/credential-provider-node": "3.398.0", - "@aws-sdk/middleware-host-header": "3.398.0", - "@aws-sdk/middleware-logger": "3.398.0", - "@aws-sdk/middleware-recursion-detection": "3.398.0", - "@aws-sdk/middleware-signing": "3.398.0", - "@aws-sdk/middleware-user-agent": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@aws-sdk/util-endpoints": "3.398.0", - "@aws-sdk/util-user-agent-browser": "3.398.0", - "@aws-sdk/util-user-agent-node": "3.398.0", - "@smithy/config-resolver": "^2.0.5", - "@smithy/fetch-http-handler": "^2.0.5", - "@smithy/hash-node": "^2.0.5", - "@smithy/invalid-dependency": "^2.0.5", - "@smithy/middleware-content-length": "^2.0.5", - "@smithy/middleware-endpoint": "^2.0.5", - "@smithy/middleware-retry": "^2.0.5", - "@smithy/middleware-serde": "^2.0.5", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/node-http-handler": "^2.0.5", - "@smithy/protocol-http": "^2.0.5", - "@smithy/smithy-client": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.5", - "@smithy/util-defaults-mode-node": "^2.0.5", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sso": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.398.0.tgz", - "integrity": "sha512-CygL0jhfibw4kmWXG/3sfZMFNjcXo66XUuPC4BqZBk8Rj5vFoxp1vZeMkDLzTIk97Nvo5J5Bh+QnXKhub6AckQ==", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.398.0", - "@aws-sdk/middleware-logger": "3.398.0", - "@aws-sdk/middleware-recursion-detection": "3.398.0", - "@aws-sdk/middleware-user-agent": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@aws-sdk/util-endpoints": "3.398.0", - "@aws-sdk/util-user-agent-browser": "3.398.0", - "@aws-sdk/util-user-agent-node": "3.398.0", - "@smithy/config-resolver": "^2.0.5", - "@smithy/fetch-http-handler": "^2.0.5", - "@smithy/hash-node": "^2.0.5", - "@smithy/invalid-dependency": "^2.0.5", - "@smithy/middleware-content-length": "^2.0.5", - "@smithy/middleware-endpoint": "^2.0.5", - "@smithy/middleware-retry": "^2.0.5", - "@smithy/middleware-serde": "^2.0.5", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/node-http-handler": "^2.0.5", - "@smithy/protocol-http": "^2.0.5", - "@smithy/smithy-client": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.5", - "@smithy/util-defaults-mode-node": "^2.0.5", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/client-sts": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.398.0.tgz", - "integrity": "sha512-/3Pa9wLMvBZipKraq3AtbmTfXW6q9kyvhwOno64f1Fz7kFb8ijQFMGoATS70B2pGEZTlxkUqJFWDiisT6Q6dFg==", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.398.0", - "@aws-sdk/middleware-host-header": "3.398.0", - "@aws-sdk/middleware-logger": "3.398.0", - "@aws-sdk/middleware-recursion-detection": "3.398.0", - "@aws-sdk/middleware-sdk-sts": "3.398.0", - "@aws-sdk/middleware-signing": "3.398.0", - "@aws-sdk/middleware-user-agent": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@aws-sdk/util-endpoints": "3.398.0", - "@aws-sdk/util-user-agent-browser": "3.398.0", - "@aws-sdk/util-user-agent-node": "3.398.0", - "@smithy/config-resolver": "^2.0.5", - "@smithy/fetch-http-handler": "^2.0.5", - "@smithy/hash-node": "^2.0.5", - "@smithy/invalid-dependency": "^2.0.5", - "@smithy/middleware-content-length": "^2.0.5", - "@smithy/middleware-endpoint": "^2.0.5", - "@smithy/middleware-retry": "^2.0.5", - "@smithy/middleware-serde": "^2.0.5", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/node-http-handler": "^2.0.5", - "@smithy/protocol-http": "^2.0.5", - "@smithy/smithy-client": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.5", - "@smithy/util-defaults-mode-node": "^2.0.5", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-cognito-identity": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.398.0.tgz", - "integrity": "sha512-MFUhy1YayHg5ypRTk4OTfDumQRP+OJBagaGv14kA8DzhKH1sNrU4HV7A7y2J4SvkN5hG/KnLJqxpakCtB2/O2g==", - "optional": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-env": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.398.0.tgz", - "integrity": "sha512-Z8Yj5z7FroAsR6UVML+XUdlpoqEe9Dnle8c2h8/xWwIC2feTfIBhjLhRVxfbpbM1pLgBSNEcZ7U8fwq5l7ESVQ==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.398.0.tgz", - "integrity": "sha512-AsK1lStK3nB9Cn6S6ODb1ktGh7SRejsNVQVKX3t5d3tgOaX+aX1Iwy8FzM/ZEN8uCloeRifUGIY9uQFygg5mSw==", - "optional": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.398.0", - "@aws-sdk/credential-provider-process": "3.398.0", - "@aws-sdk/credential-provider-sso": "3.398.0", - "@aws-sdk/credential-provider-web-identity": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.398.0.tgz", - "integrity": "sha512-odmI/DSKfuWUYeDnGTCEHBbC8/MwnF6yEq874zl6+owoVv0ZsYP8qBHfiJkYqrwg7wQ7Pi40sSAPC1rhesGwzg==", - "optional": true, - "requires": { - "@aws-sdk/credential-provider-env": "3.398.0", - "@aws-sdk/credential-provider-ini": "3.398.0", - "@aws-sdk/credential-provider-process": "3.398.0", - "@aws-sdk/credential-provider-sso": "3.398.0", - "@aws-sdk/credential-provider-web-identity": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-process": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.398.0.tgz", - "integrity": "sha512-WrkBL1W7TXN508PA9wRXPFtzmGpVSW98gDaHEaa8GolAPHMPa5t2QcC/z/cFpglzrcVv8SA277zu9Z8tELdZhg==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.398.0.tgz", - "integrity": "sha512-2Dl35587xbnzR/GGZqA2MnFs8+kS4wbHQO9BioU0okA+8NRueohNMdrdQmQDdSNK4BfIpFspiZmFkXFNyEAfgw==", - "optional": true, - "requires": { - "@aws-sdk/client-sso": "3.398.0", - "@aws-sdk/token-providers": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/credential-provider-web-identity": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.398.0.tgz", - "integrity": "sha512-iG3905Alv9pINbQ8/MIsshgqYMbWx+NDQWpxbIW3W0MkSH3iAqdVpSCteYidYX9G/jv2Um1nW3y360ib20bvNg==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, "@aws-sdk/credential-providers": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.398.0.tgz", - "integrity": "sha512-355vXmImn2e85mIWSYDVb101AF2lIVHKNCaH6sV1U/8i0ZOXh2cJYNdkRYrxNt1ezDB0k97lSKvuDx7RDvJyRg==", - "optional": true, - "requires": { - "@aws-sdk/client-cognito-identity": "3.398.0", - "@aws-sdk/client-sso": "3.398.0", - "@aws-sdk/client-sts": "3.398.0", - "@aws-sdk/credential-provider-cognito-identity": "3.398.0", - "@aws-sdk/credential-provider-env": "3.398.0", - "@aws-sdk/credential-provider-ini": "3.398.0", - "@aws-sdk/credential-provider-node": "3.398.0", - "@aws-sdk/credential-provider-process": "3.398.0", - "@aws-sdk/credential-provider-sso": "3.398.0", - "@aws-sdk/credential-provider-web-identity": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-host-header": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.398.0.tgz", - "integrity": "sha512-m+5laWdBaxIZK2ko0OwcCHJZJ5V1MgEIt8QVQ3k4/kOkN9ICjevOYmba751pHoTnbOYB7zQd6D2OT3EYEEsUcA==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/protocol-http": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-logger": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.398.0.tgz", - "integrity": "sha512-CiJjW+FL12elS6Pn7/UVjVK8HWHhXMfvHZvOwx/Qkpy340sIhkuzOO6fZEruECDTZhl2Wqn81XdJ1ZQ4pRKpCg==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-recursion-detection": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.398.0.tgz", - "integrity": "sha512-7QpOqPQAZNXDXv6vsRex4R8dLniL0E/80OPK4PPFsrCh9btEyhN9Begh4i1T+5lL28hmYkztLOkTQ2N5J3hgRQ==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/protocol-http": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.398.0.tgz", - "integrity": "sha512-+JH76XHEgfVihkY+GurohOQ5Z83zVN1nYcQzwCFnCDTh4dG4KwhnZKG+WPw6XJECocY0R+H0ivofeALHvVWJtQ==", - "optional": true, - "requires": { - "@aws-sdk/middleware-signing": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.398.0.tgz", - "integrity": "sha512-O0KqXAix1TcvZBFt1qoFkHMUNJOSgjJTYS7lFTRKSwgsD27bdW2TM2r9R8DAccWFt5Amjkdt+eOwQMIXPGTm8w==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.5", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.2.2", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/middleware-user-agent": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.398.0.tgz", - "integrity": "sha512-nF1jg0L+18b5HvTcYzwyFgfZQQMELJINFqI0mi4yRKaX7T5a3aGp5RVLGGju/6tAGTuFbfBoEhkhU3kkxexPYQ==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@aws-sdk/util-endpoints": "3.398.0", - "@smithy/protocol-http": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/token-providers": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.398.0.tgz", - "integrity": "sha512-nrYgjzavGCKJL/48Vt0EL+OlIc5UZLfNGpgyUW9cv3XZwl+kXV0QB+HH0rHZZLfpbBgZ2RBIJR9uD5ieu/6hpQ==", - "optional": true, - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.398.0", - "@aws-sdk/middleware-logger": "3.398.0", - "@aws-sdk/middleware-recursion-detection": "3.398.0", - "@aws-sdk/middleware-user-agent": "3.398.0", - "@aws-sdk/types": "3.398.0", - "@aws-sdk/util-endpoints": "3.398.0", - "@aws-sdk/util-user-agent-browser": "3.398.0", - "@aws-sdk/util-user-agent-node": "3.398.0", - "@smithy/config-resolver": "^2.0.5", - "@smithy/fetch-http-handler": "^2.0.5", - "@smithy/hash-node": "^2.0.5", - "@smithy/invalid-dependency": "^2.0.5", - "@smithy/middleware-content-length": "^2.0.5", - "@smithy/middleware-endpoint": "^2.0.5", - "@smithy/middleware-retry": "^2.0.5", - "@smithy/middleware-serde": "^2.0.5", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/node-http-handler": "^2.0.5", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^2.0.5", - "@smithy/shared-ini-file-loader": "^2.0.0", - "@smithy/smithy-client": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.5", - "@smithy/util-defaults-mode-node": "^2.0.5", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/types": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.398.0.tgz", - "integrity": "sha512-r44fkS+vsEgKCuEuTV+TIk0t0m5ZlXHNjSDYEUvzLStbbfUFiNus/YG4UCa0wOk9R7VuQI67badsvvPeVPCGDQ==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-endpoints": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.398.0.tgz", - "integrity": "sha512-Fy0gLYAei/Rd6BrXG4baspCnWTUSd0NdokU1pZh4KlfEAEN1i8SPPgfiO5hLk7+2inqtCmqxVJlfqbMVe9k4bw==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-browser": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.398.0.tgz", - "integrity": "sha512-A3Tzx1tkDHlBT+IgxmsMCHbV8LM7SwwCozq2ZjJRx0nqw3MCrrcxQFXldHeX/gdUMO+0Oocb7HGSnVODTq+0EA==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/types": "^2.2.2", - "bowser": "^2.11.0", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-user-agent-node": { - "version": "3.398.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.398.0.tgz", - "integrity": "sha512-RTVQofdj961ej4//fEkppFf4KXqKGMTCqJYghx3G0C/MYXbg7MGl7LjfNGtJcboRE8pfHHQ/TUWBDA7RIAPPlQ==", - "optional": true, - "requires": { - "@aws-sdk/types": "3.398.0", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "optional": true, - "requires": { - "tslib": "^2.3.1" - } - }, - "@mongodb-js/saslprep": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", - "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", - "optional": true, - "requires": { - "sparse-bitfield": "^3.0.3" - } - }, - "@smithy/abort-controller": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.5.tgz", - "integrity": "sha512-byVZ2KWLMPYAZGKjRpniAzLcygJO4ruClZKdJTuB0eCB76ONFTdptBHlviHpAZXknRz7skYWPfcgO9v30A1SyA==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/config-resolver": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.5.tgz", - "integrity": "sha512-n0c2AXz+kjALY2FQr7Zy9zhYigXzboIh1AuUUVCqFBKFtdEvTwnwPXrTDoEehLiRTUHNL+4yzZ3s+D0kKYSLSg==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/credential-provider-imds": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.5.tgz", - "integrity": "sha512-KFcf/e0meFkQNyteJ65f1G19sgUEY1e5zL7hyAEUPz2SEfBmC9B37WyRq87G3MEEsvmAWwCRu7nFFYUKtR3svQ==", - "optional": true, - "requires": { - "@smithy/node-config-provider": "^2.0.5", - "@smithy/property-provider": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "tslib": "^2.5.0" - } - }, - "@smithy/eventstream-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.5.tgz", - "integrity": "sha512-iqR6OuOV3zbQK8uVs9o+9AxhVk8kW9NAxA71nugwUB+kTY9C35pUd0A5/m4PRT0Y0oIW7W4kgnSR3fdYXQjECw==", - "optional": true, - "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.2.2", - "@smithy/util-hex-encoding": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/fetch-http-handler": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.0.5.tgz", - "integrity": "sha512-EzFoMowdBNy1VqtvkiXgPFEdosIAt4/4bgZ8uiDiUyfhmNXq/3bV+CagPFFBsgFOR/X2XK4zFZHRsoa7PNHVVg==", - "optional": true, - "requires": { - "@smithy/protocol-http": "^2.0.5", - "@smithy/querystring-builder": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/util-base64": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/hash-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.5.tgz", - "integrity": "sha512-mk551hIywBITT+kXruRNXk7f8Fy7DTzBjZJSr/V6nolYKmUHIG3w5QU6nO9qPYEQGKc/yEPtkpdS28ndeG93lA==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/invalid-dependency": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.5.tgz", - "integrity": "sha512-0wEi+JT0hM+UUwrJVYbqjuGFhy5agY/zXyiN7BNAJ1XoCDjU5uaNSj8ekPWsXd/d4yM6NSe8UbPd8cOc1+3oBQ==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-content-length": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.5.tgz", - "integrity": "sha512-E7VwV5H02fgZIUGRli4GevBCAPvkyEI/fgl9SU47nPPi3DAAX3nEtUb8xfGbXjOcJ5BdSUoWWZn42tEd/blOqA==", - "optional": true, - "requires": { - "@smithy/protocol-http": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-endpoint": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.5.tgz", - "integrity": "sha512-tyzDuoNTbsMQCq5Xkc4QOt6e2GACUllQIV8SQ5fc59FtOIV9/vbf58/GxVjZm2o8+MMbdDBANjTDZe/ijZKfyA==", - "optional": true, - "requires": { - "@smithy/middleware-serde": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/url-parser": "^2.0.5", - "@smithy/util-middleware": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-retry": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.5.tgz", - "integrity": "sha512-ulIfbFyzQTVnJbLjUl1CTSi0etg6tej/ekwaLp0Gn8ybUkDkKYa+uB6CF/m2J5B6meRwyJlsryR+DjaOVyiicg==", - "optional": true, - "requires": { - "@smithy/protocol-http": "^2.0.5", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.2.2", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", - "tslib": "^2.5.0", - "uuid": "^8.3.2" + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.621.0.tgz", + "integrity": "sha512-FQbC7I8ae/72ZekLBa45jWJ+Q3d+YPhc3bW/rCks6RrldM6RgLTGr8pTOPCxHl828ky10RjkBiBmVU818rliyw==", + "requires": { + "@aws-sdk/client-cognito-identity": "3.621.0", + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/credential-provider-cognito-identity": "3.621.0", + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.621.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "optional": true - } - } - }, - "@smithy/middleware-serde": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.5.tgz", - "integrity": "sha512-in0AA5sous74dOfTGU9rMJBXJ0bDVNxwdXtEt5lh3FVd2sEyjhI+rqpLLRF1E4ixbw3RSEf80hfRpcPdjg4vvQ==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/node-config-provider": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.5.tgz", - "integrity": "sha512-LRtjV9WkhONe2lVy+ipB/l1GX60ybzBmFyeRUoLUXWKdnZ3o81jsnbKzMK8hKq8eFSWPk+Lmyx6ZzCQabGeLxg==", - "optional": true, - "requires": { - "@smithy/property-provider": "^2.0.5", - "@smithy/shared-ini-file-loader": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/node-http-handler": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.0.5.tgz", - "integrity": "sha512-lZm5DZf4b3V0saUw9WTC4/du887P6cy2fUyQgQQKRRV6OseButyD5yTzeMmXE53CaXJBMBsUvvIQ0hRVxIq56w==", - "optional": true, - "requires": { - "@smithy/abort-controller": "^2.0.5", - "@smithy/protocol-http": "^2.0.5", - "@smithy/querystring-builder": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/property-provider": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.5.tgz", - "integrity": "sha512-cAFSUhX6aiHcmpWfrCLKvwBtgN1F6A0N8qY/8yeSi0LRLmhGqsY1/YTxFE185MCVzYbqBGXVr9TBv4RUcIV4rA==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/protocol-http": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-2.0.5.tgz", - "integrity": "sha512-d2hhHj34mA2V86doiDfrsy2fNTnUOowGaf9hKb0hIPHqvcnShU4/OSc4Uf1FwHkAdYF3cFXTrj5VGUYbEuvMdw==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-builder": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.5.tgz", - "integrity": "sha512-4DCX9krxLzATj+HdFPC3i8pb7XTAWzzKqSw8aTZMjXjtQY+vhe4azMAqIvbb6g7JKwIkmkRAjK6EXO3YWSnJVQ==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "@smithy/util-uri-escape": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/querystring-parser": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.5.tgz", - "integrity": "sha512-C2stCULH0r54KBksv3AWcN8CLS3u9+WsEW8nBrvctrJ5rQTNa1waHkffpVaiKvcW2nP0aIMBPCobD/kYf/q9mA==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", - "optional": true - }, - "@smithy/shared-ini-file-loader": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.5.tgz", - "integrity": "sha512-Mvtk6FwMtfbKRC4YuSsIqRYp9WTxsSUJVVo2djgyhcacKGMqicHDWSAmgy3sDrKv+G/G6xTZCPwm6pJARtdxVg==", - "optional": true, - "requires": { - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/signature-v4": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.5.tgz", - "integrity": "sha512-ABIzXmUDXK4n2c9cXjQLELgH2RdtABpYKT+U131e2I6RbCypFZmxIHmIBufJzU2kdMCQ3+thBGDWorAITFW04A==", - "optional": true, - "requires": { - "@smithy/eventstream-codec": "^2.0.5", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.2.2", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/smithy-client": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.0.5.tgz", - "integrity": "sha512-kCTFr8wfOAWKDzGvfBElc6shHigWtHNhMQ1IbosjC4jOlayFyZMSs2PysKB+Ox/dhQ41KqOzgVjgiQ+PyWqHMQ==", - "optional": true, - "requires": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.2.2", - "@smithy/util-stream": "^2.0.5", - "tslib": "^2.5.0" - } - }, - "@smithy/types": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.2.2.tgz", - "integrity": "sha512-4PS0y1VxDnELGHGgBWlDksB2LJK8TG8lcvlWxIsgR+8vROI7Ms8h1P4FQUx+ftAX2QZv5g1CJCdhdRmQKyonyw==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/url-parser": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.5.tgz", - "integrity": "sha512-OdMBvZhpckQSkugCXNJQCvqJ71wE7Ftxce92UOQLQ9pwF6hoS5PLL7wEfpnuEXtStzBqJYkzu1C1ZfjuFGOXAA==", - "optional": true, - "requires": { - "@smithy/querystring-parser": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" - } - }, - "@smithy/util-base64": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", - "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", - "optional": true, - "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", - "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-body-length-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", - "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", - "optional": true, - "requires": { - "@smithy/is-array-buffer": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-config-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", - "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-defaults-mode-browser": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.5.tgz", - "integrity": "sha512-yciP6TPttLsj731aHTvekgyuCGXQrEAJibEwEWAh3kzaDsfGAVCuZSBlyvC2Dl3TZmHKCOQwHV8mIE7KQCTPuQ==", - "optional": true, - "requires": { - "@smithy/property-provider": "^2.0.5", - "@smithy/types": "^2.2.2", - "bowser": "^2.11.0", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + } + } + }, + "@aws-sdk/client-cognito-identity": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.621.0.tgz", + "integrity": "sha512-FpXia5qFf6ijcNDWenVq+mP9r1LbiW/+52i9wrv2+Afi6Nn1ROf8W7St8WvE9TEZ3t78y+vis4CwqfGts+uiKA==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/client-sts": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/client-sso": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.621.0.tgz", + "integrity": "sha512-xpKfikN4u0BaUYZA9FGUMkkDmfoIP0Q03+A86WjqDWhcOoqNA1DkHsE4kZ+r064ifkPUfcNuUvlkVTEoBZoFjA==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/client-sts": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.621.0.tgz", + "integrity": "sha512-707uiuReSt+nAx6d0c21xLjLm2lxeKc7padxjv92CIrIocnQSlJPxSCM7r5zBhwiahJA6MNQwmTl2xznU67KgA==", + "requires": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.621.0", + "@aws-sdk/core": "3.621.0", + "@aws-sdk/credential-provider-node": "3.621.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.620.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.3.1", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.13", + "@smithy/util-defaults-mode-node": "^3.0.13", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-cognito-identity": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.621.0.tgz", + "integrity": "sha512-Q+3awvTVJSqIGRjCUQflRwKPKlZ0TfmL3EQHgFLhZZrToeBapEA62+FY+T70aTKAZZZZprlvYeFPtBloNd5ziA==", + "requires": { + "@aws-sdk/client-cognito-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-env": { + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-ini": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.621.0.tgz", + "integrity": "sha512-0EWVnSc+JQn5HLnF5Xv405M8n4zfdx9gyGdpnCmAmFqEDHA8LmBdxJdpUk1Ovp/I5oPANhjojxabIW5f1uU0RA==", + "requires": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.621.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-node": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.621.0.tgz", + "integrity": "sha512-4JqpccUgz5Snanpt2+53hbOBbJQrSFq7E1sAAbgY6BKVQUsW5qyXqnjvSF32kDeKa5JpBl3bBWLZl04IadcPHw==", + "requires": { + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.621.0", + "@aws-sdk/credential-provider-ini": "3.621.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.621.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-process": { + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-sso": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.621.0.tgz", + "integrity": "sha512-Kza0jcFeA/GEL6xJlzR2KFf1PfZKMFnxfGzJzl5yN7EjoGdMijl34KaRyVnfRjnCWcsUpBWKNIDk9WZVMY9yiw==", + "requires": { + "@aws-sdk/client-sso": "3.621.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/credential-provider-web-identity": { + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-host-header": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-logger": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-recursion-detection": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/middleware-user-agent": { + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", + "integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.614.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/token-providers": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-endpoints": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz", + "integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-browser": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@aws-sdk/util-user-agent-node": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/config-resolver": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/credential-provider-imds": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", + "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/hash-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/invalid-dependency": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-content-length": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", + "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "requires": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-retry": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + } + }, + "@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "requires": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "requires": { + "@smithy/types": "^3.3.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "requires": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-browser": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.13.tgz", + "integrity": "sha512-ZIRSUsnnMRStOP6OKtW+gCSiVFkwnfQF2xtf32QKAbHR6ACjhbAybDvry+3L5qQYdh3H6+7yD/AiUE45n8mTTw==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-defaults-mode-node": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.13.tgz", + "integrity": "sha512-voUa8TFJGfD+U12tlNNLCDlXibt9vRdNzRX45Onk/WxZe7TS+hTOZouEZRa7oARGicdgeXvt1A0W45qLGYdy+g==", + "requires": { + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "requires": { + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "requires": { + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + } + } + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + } } }, - "@smithy/util-defaults-mode-node": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.5.tgz", - "integrity": "sha512-M07t99rWasXt+IaDZDyP3BkcoEm/mgIE1RIMASrE49LKSNxaVN7PVcgGc77+4uu2kzBAyqJKy79pgtezuknyjQ==", - "optional": true, + "@aws-sdk/region-config-resolver": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", "requires": { - "@smithy/config-resolver": "^2.0.5", - "@smithy/credential-provider-imds": "^2.0.5", - "@smithy/node-config-provider": "^2.0.5", - "@smithy/property-provider": "^2.0.5", - "@smithy/types": "^2.2.2", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "dependencies": { + "@aws-sdk/types": { + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + } } }, - "@smithy/util-hex-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", - "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", - "optional": true, + "@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "requires": { "tslib": "^2.5.0" } }, - "@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", + "@mongodb-js/saslprep": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz", + "integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==", "optional": true, "requires": { - "tslib": "^2.5.0" + "sparse-bitfield": "^3.0.3" } }, - "@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", - "optional": true, - "requires": { - "@smithy/service-error-classification": "^2.0.0", - "tslib": "^2.5.0" + "@smithy/core": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.3.1.tgz", + "integrity": "sha512-BC7VMXx/1BCmRPCVzzn4HGWAtsrb7/0758EtwOGFJQrlSwJBEjCcDLNZLFoL/68JexYa2s+KmgL/UfmXdG6v1w==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.13", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/fetch-http-handler": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "requires": { + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-endpoint": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "requires": { + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-retry": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.13.tgz", + "integrity": "sha512-zvCLfaRYCaUmjbF2yxShGZdolSHft7NNCTA28HVN9hKcEbOH+g5irr1X9s+in8EpambclGnevZY4A3lYpvDCFw==", + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.1.11", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + } + }, + "@smithy/middleware-serde": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/middleware-stack": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/node-http-handler": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "requires": { + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/protocol-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-builder": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/querystring-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/service-error-classification": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "requires": { + "@smithy/types": "^3.3.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/smithy-client": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.11.tgz", + "integrity": "sha512-l0BpyYkciNyMaS+PnFFz4aO5sBcXvGLoJd7mX9xrMBIm2nIQBVvYgp2ZpPDMzwjKCavsXu06iuCm0F6ZJZc6yQ==", + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/url-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "requires": { + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "requires": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-middleware": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "requires": { + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-stream": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "requires": { + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "requires": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + } } }, - "@smithy/util-stream": { + "@smithy/util-endpoints": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.5.tgz", - "integrity": "sha512-ylx27GwI05xLpYQ4hDIfS15vm+wYjNN0Sc2P0FxuzgRe8v0BOLHppGIQ+Bezcynk8C9nUzsUue3TmtRhjut43g==", - "optional": true, - "requires": { - "@smithy/fetch-http-handler": "^2.0.5", - "@smithy/node-http-handler": "^2.0.5", - "@smithy/types": "^2.2.2", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", - "tslib": "^2.5.0" - } - }, - "@smithy/util-uri-escape": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", - "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", - "optional": true, - "requires": { - "tslib": "^2.5.0" - } - }, - "@smithy/util-utf8": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", - "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", - "optional": true, + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", + "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", "requires": { - "@smithy/util-buffer-from": "^2.0.0", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/node-config-provider": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "requires": { + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/property-provider": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "@smithy/types": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "requires": { + "tslib": "^2.6.2" + } + } } }, "@srfnstack/spliffy": { @@ -1032,8 +2665,7 @@ "bowser": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "optional": true + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, "bson": { "version": "4.7.2", @@ -1082,15 +2714,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, - "fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", - "optional": true, - "requires": { - "strnum": "^1.0.5" - } - }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -1435,8 +3058,7 @@ "strnum": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "optional": true + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "tr46": { "version": "3.0.0", @@ -1449,8 +3071,7 @@ "tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", - "optional": true + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "uWebSockets.js": { "version": "github:uNetworking/uWebSockets.js#7bf0faac5859fef2d113e83d22803f7833774c11", From 64e6ae6f6f4714f9c22632e05408aeef4aeb4b01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 02:09:55 +0000 Subject: [PATCH 57/62] Bump rexml from 3.3.1 to 3.3.3 in /frameworks/Ruby/rack Bumps [rexml](https://github.com/ruby/rexml) from 3.3.1 to 3.3.3. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.3.1...v3.3.3) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frameworks/Ruby/rack/Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Ruby/rack/Gemfile.lock b/frameworks/Ruby/rack/Gemfile.lock index 0fa04f72580..7a08fdf7195 100644 --- a/frameworks/Ruby/rack/Gemfile.lock +++ b/frameworks/Ruby/rack/Gemfile.lock @@ -86,7 +86,7 @@ GEM rainbow (3.1.1) raindrops (0.20.1) regexp_parser (2.9.2) - rexml (3.3.1) + rexml (3.3.3) strscan rubocop (1.64.1) json (~> 2.3) From 912fb4827743ca029e8abb128eaf5f5ec1acb3c0 Mon Sep 17 00:00:00 2001 From: Rasmus Porsager Date: Fri, 2 Aug 2024 17:59:01 +0200 Subject: [PATCH 58/62] Add uwebsocketsjs (#9189) * Revert "Remove uwebsockets (#9160)" This reverts commit 4b0a91f07147386c8f11b36b1410f00b34c7611c. * Remove mysql * Don't fetch types on connect --- .../JavaScript/uwebsockets.js/README.md | 52 +++++ .../uwebsockets.js/benchmark_config.json | 47 +++++ .../uwebsockets.js/package-lock.json | 39 ++++ .../JavaScript/uwebsockets.js/package.json | 17 ++ .../uwebsockets.js/src/clustered.js | 23 +++ .../uwebsockets.js/src/database/postgres.js | 18 ++ .../JavaScript/uwebsockets.js/src/server.js | 194 ++++++++++++++++++ .../JavaScript/uwebsockets.js/src/utils.js | 86 ++++++++ .../uwebsockets.js-postgres.dockerfile | 12 ++ .../uwebsockets.js/uwebsockets.js.dockerfile | 11 + 10 files changed, 499 insertions(+) create mode 100644 frameworks/JavaScript/uwebsockets.js/README.md create mode 100644 frameworks/JavaScript/uwebsockets.js/benchmark_config.json create mode 100644 frameworks/JavaScript/uwebsockets.js/package-lock.json create mode 100644 frameworks/JavaScript/uwebsockets.js/package.json create mode 100644 frameworks/JavaScript/uwebsockets.js/src/clustered.js create mode 100644 frameworks/JavaScript/uwebsockets.js/src/database/postgres.js create mode 100644 frameworks/JavaScript/uwebsockets.js/src/server.js create mode 100644 frameworks/JavaScript/uwebsockets.js/src/utils.js create mode 100644 frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile create mode 100644 frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile diff --git a/frameworks/JavaScript/uwebsockets.js/README.md b/frameworks/JavaScript/uwebsockets.js/README.md new file mode 100644 index 00000000000..bc59e8c3026 --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/README.md @@ -0,0 +1,52 @@ +# uWebSockets.js Benchmarking Test + +uWebSockets is a web server written in C/C++ (https://github.com/uNetworking/uWebSockets) + +µWebSockets.js is a web server bypass for Node.js (https://github.com/uNetworking/uWebSockets.js) + +## Important Libraries + +The tests were run with: + +- [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js/) +- [postgres](https://github.com/porsager/postgres/) + +## Database + +There are individual handlers for each DB approach. The logic for each of them are found here: + +- [PostgreSQL](src/database/postgres.js) + +There are **no database endpoints** or drivers attached by default. + +To initialize the application with one of these, run any _one_ of the following commands: + +```sh +$ DATABASE=postgres npm start +``` + +## Test Endpoints + +> Visit the test requirements [here](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview) + +```sh +$ curl localhost:8080/json +$ curl localhost:8080/plaintext + +# The following are only available with the DATABASE env var + +$ curl localhost:8080/db +$ curl localhost:8080/fortunes + +$ curl localhost:8080/updates?queries= +$ curl localhost:8080/updates?queries=2 +$ curl localhost:8080/updates?queries=1000 +$ curl localhost:8080/updates?queries=foo +$ curl localhost:8080/updates?queries=0 + +$ curl localhost:8080/queries?queries= +$ curl localhost:8080/queries?queries=2 +$ curl localhost:8080/queries?queries=1000 +$ curl localhost:8080/queries?queries=foo +$ curl localhost:8080/queries?queries=0 +``` diff --git a/frameworks/JavaScript/uwebsockets.js/benchmark_config.json b/frameworks/JavaScript/uwebsockets.js/benchmark_config.json new file mode 100644 index 00000000000..a0ac515dcfe --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/benchmark_config.json @@ -0,0 +1,47 @@ +{ + "framework": "uwebsockets.js", + "tests": [ + { + "default": { + "approach": "Realistic", + "classification": "Platform", + "database": "None", + "database_os": "Linux", + "display_name": "uWebSockets.js", + "flavor": "NodeJS", + "framework": "uWebSockets.js", + "json_url": "/json", + "language": "JavaScript", + "notes": "", + "orm": "Raw", + "os": "Linux", + "plaintext_url": "/plaintext", + "platform": "nodejs", + "port": 8080, + "versus": "nodejs", + "webserver": "None" + }, + "postgres": { + "approach": "Realistic", + "classification": "Platform", + "database": "Postgres", + "database_os": "Linux", + "db_url": "/db", + "display_name": "uWebSockets.js", + "flavor": "NodeJS", + "fortune_url": "/fortunes", + "framework": "uWebSockets.js", + "language": "JavaScript", + "notes": "", + "orm": "Raw", + "os": "Linux", + "platform": "None", + "port": 8080, + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "versus": "nodejs", + "webserver": "None" + } + } + ] +} diff --git a/frameworks/JavaScript/uwebsockets.js/package-lock.json b/frameworks/JavaScript/uwebsockets.js/package-lock.json new file mode 100644 index 00000000000..13fff11e161 --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/package-lock.json @@ -0,0 +1,39 @@ +{ + "name": "uwebsockets.js", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "uwebsockets.js", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "postgres": "3.4.4", + "slow-json-stringify": "^2.0.1", + "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" + } + }, + "node_modules/postgres": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.4.4.tgz", + "integrity": "sha512-IbyN+9KslkqcXa8AO9fxpk97PA4pzewvpi2B3Dwy9u4zpV32QicaEdgmF3eSQUzdRk7ttDHQejNgAEr4XoeH4A==", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/porsager" + } + }, + "node_modules/slow-json-stringify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/slow-json-stringify/-/slow-json-stringify-2.0.1.tgz", + "integrity": "sha512-jqyzIqTaSkRGcWdWqjmOLKHZgOGUT71ZCTsvQu1xGu9Mqaod7O26y5FJJEmaUQhaTWh0bkXv2qqN0i+EQsD1jQ==" + }, + "node_modules/uWebSockets.js": { + "version": "20.44.0", + "resolved": "git+ssh://git@github.com/uNetworking/uWebSockets.js.git#8fa05571bf6ea95be8966ad313d9d39453e381ae" + } + } +} diff --git a/frameworks/JavaScript/uwebsockets.js/package.json b/frameworks/JavaScript/uwebsockets.js/package.json new file mode 100644 index 00000000000..635c0a2b12a --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/package.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "postgres": "3.4.4", + "slow-json-stringify": "^2.0.1", + "uWebSockets.js": "uNetworking/uWebSockets.js#v20.44.0" + }, + "license": "MIT", + "main": "src/server.js", + "name": "uwebsockets.js", + "private": true, + "scripts": { + "dev": "node src/server.js", + "start": "node src/clustered.js" + }, + "type": "module", + "version": "0.0.1" +} diff --git a/frameworks/JavaScript/uwebsockets.js/src/clustered.js b/frameworks/JavaScript/uwebsockets.js/src/clustered.js new file mode 100644 index 00000000000..95a57ec77f3 --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/src/clustered.js @@ -0,0 +1,23 @@ +import cluster from "node:cluster"; +import os from "node:os"; +import process from "node:process"; + +if (cluster.isPrimary) { + // Master Node + console.log(`Primary ${process.pid} is running`); + + // Fork workers + const numCPUs = os.availableParallelism(); + for (let i = 0; i < numCPUs; i++) { + cluster.fork(); + } + + cluster.on("exit", (worker) => { + console.log(`worker ${worker.process.pid} died`); + process.exit(1); + }); +} else { + // Cluster Node + await import("./server.js"); + console.log(`Worker ${process.pid} started`); +} diff --git a/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js b/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js new file mode 100644 index 00000000000..db262a9757d --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/src/database/postgres.js @@ -0,0 +1,18 @@ +import postgres from "postgres"; + +const sql = postgres({ + host: "tfb-database", + user: "benchmarkdbuser", + password: "benchmarkdbpass", + database: "hello_world", + fetch_types: false, + max: 1 +}); + +export const fortunes = async () => await sql`SELECT id, message FROM fortune`; + +export const find = async (id) => await sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then((arr) => arr[0]); + +export const bulkUpdate = async (worlds) => await sql`UPDATE world SET randomNumber = (update_data.randomNumber)::int + FROM (VALUES ${sql(worlds.map(world => [world.id, world.randomNumber]).sort((a, b) => (a[0] < b[0]) ? -1 : 1))}) AS update_data (id, randomNumber) + WHERE world.id = (update_data.id)::int`; diff --git a/frameworks/JavaScript/uwebsockets.js/src/server.js b/frameworks/JavaScript/uwebsockets.js/src/server.js new file mode 100644 index 00000000000..1db7d391f2a --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/src/server.js @@ -0,0 +1,194 @@ +import uWebSockets from "uWebSockets.js"; +import { + addBenchmarkHeaders, + generateRandomNumber, + getQueriesCount, + handleError, + escape, + jsonSerializer, + worldObjectSerializer, + sortByMessage +} from "./utils.js"; + +let db; +const { DATABASE } = process.env; +if (DATABASE) db = await import(`./database/${DATABASE}.js`); + +const webserver = uWebSockets.App(); + +webserver.get("/plaintext", new uWebSockets.DeclarativeResponse() + .writeHeader("Server", "uWebSockets.js") + .writeHeader("Content-Type", "text/plain") + .end("Hello, World!") +); + +webserver.get("/json", (response) => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "application/json"); + // response.end(JSON.stringify({ message: "Hello, World!" })); + response.end(jsonSerializer({ message: "Hello, World!" })); +}); + +if (db) { + webserver.get("/db", async (response) => { + response.onAborted(() => { + response.aborted = true; + }); + + try { + const row = await db.find(generateRandomNumber()); + + if (response.aborted) { + return; + } + + response.cork(() => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "application/json"); + // response.end(JSON.stringify(rows)); + response.end(worldObjectSerializer(row)); + }); + } catch (error) { + if (response.aborted) { + return; + } + + handleError(error, response); + } + }); + + webserver.get("/queries", async (response, request) => { + response.onAborted(() => { + response.aborted = true; + }); + + try { + const queriesCount = getQueriesCount(request); + + const databaseJobs = new Array(queriesCount); + + for (let i = 0; i < queriesCount; i++) { + databaseJobs[i] = db.find(generateRandomNumber()); + } + + const worldObjects = await Promise.all(databaseJobs); + + if (response.aborted) { + return; + } + + response.cork(() => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "application/json"); + response.end(JSON.stringify(worldObjects)); + }); + } catch (error) { + if (response.aborted) { + return; + } + + handleError(error, response); + } + }); + + const extra = { id: 0, message: "Additional fortune added at request time." }; + + webserver.get("/fortunes", async (response) => { + response.onAborted(() => { + response.aborted = true; + }); + + try { + const rows = [extra, ...await db.fortunes()]; + + if (response.aborted) { + return; + } + + // rows.push({ + // id: 0, + // message: "Additional fortune added at request time.", + // }); + + // rows.sort((a, b) => (a.message < b.message) ? -1 : 1); + sortByMessage(rows) + + const n = rows.length + + let html = "", i = 0; + for (; i < n; i++) { + html += `${rows[i].id}${escape(rows[i].message)}`; + } + + response.cork(() => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "text/html; charset=utf-8"); + response.end(`Fortunes${html}
idmessage
`); + }); + } catch (error) { + if (response.aborted) { + return; + } + + handleError(error, response); + } + }); + + webserver.get("/updates", async (response, request) => { + response.onAborted(() => { + response.aborted = true; + }); + + try { + const queriesCount = getQueriesCount(request); + + const databaseJobs = new Array(queriesCount); + + for (let i = 0; i < queriesCount; i++) { + databaseJobs[i] = db.find(generateRandomNumber()); + } + + const worldObjects = await Promise.all(databaseJobs); + + for (let i = 0; i < queriesCount; i++) { + worldObjects[i].randomNumber = generateRandomNumber(); + } + + await db.bulkUpdate(worldObjects); + + if (response.aborted) { + return; + } + + response.cork(() => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "application/json"); + response.end(JSON.stringify(worldObjects)); + }); + } catch (error) { + if (response.aborted) { + return; + } + + handleError(error, response); + } + }); +} + +webserver.any("/*", (response) => { + response.writeStatus("404 Not Found"); + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "text/plain"); + response.end("Not Found"); +}); + +const host = process.env.HOST || "0.0.0.0"; +const port = parseInt(process.env.PORT || "8080"); +webserver.listen(host, port, (socket) => { + if (!socket) { + console.error(`Couldn't bind to http://${host}:${port}!`); + process.exit(1); + } + + console.log(`Successfully bound to http://${host}:${port}.`); +}); diff --git a/frameworks/JavaScript/uwebsockets.js/src/utils.js b/frameworks/JavaScript/uwebsockets.js/src/utils.js new file mode 100644 index 00000000000..b3d46e7e11c --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/src/utils.js @@ -0,0 +1,86 @@ +import { sjs, attr } from 'slow-json-stringify' + +/** + * Add Benchmark HTTP response headers. + * + * Add HTTP response headers `Server` which is required by the test suite. + * Header `Date` is automatically added by uWebsockets + * https://github.com/uNetworking/uWebSockets/blob/master/src/HttpResponse.h#L78 + * + * https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview + * + * @param {import('uWebSockets.js').HttpResponse} response + */ +export function addBenchmarkHeaders(response) { + response.writeHeader("Server", "uWebSockets.js"); +} + +/** + * Handle error for response + * + * @param {Error} error + * @param {import('uWebSockets.js').HttpResponse} response + */ +export function handleError(error, response) { + console.error(error); + response.cork(() => { + addBenchmarkHeaders(response); + response.writeHeader("Content-Type", "text/plain"); + response.end("Internal Server Error"); + }); +} + +/** + * Get queries count + * + * @param {import('uWebSockets.js').HttpRequest} request + */ +export function getQueriesCount(request) { + return Math.min(parseInt(request.getQuery("queries")) || 1, 500); +} + +/** + * Generate random number + * + */ +export function generateRandomNumber() { + return Math.ceil(Math.random() * 10000); +} + +/** + * Escape unsafe HTML Code + * + */ +const escapeHTMLRules = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/' } + +const unsafeHTMLMatcher = /[&<>"'\/]/g + +export function escape(text) { + if (unsafeHTMLMatcher.test(text) === false) return text; + return text.replace(unsafeHTMLMatcher, function (m) { return escapeHTMLRules[m] || m; }); +} + +/** + * Using Slow json stringify module to get faster results + */ +export const jsonSerializer = sjs({ message: attr("string")}); +export const worldObjectSerializer = sjs({ id: attr('number'), randomnumber: attr('number') }); +// export const worldObjectsSerializer = sjs({ rows: attr("array", worldObjectSerializer) }); + +/** + * Using Sort method which is performant for the test scenario + * @returns + */ +export function sortByMessage (arr) { + const n = arr.length + for (let i = 1; i < n; i++) { + const c = arr[i] + let j = i - 1 + while ((j > -1) && (c.message < arr[j].message)) { + arr[j + 1] = arr[j] + j-- + } + arr[j + 1] = c + } + return arr +} \ No newline at end of file diff --git a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile new file mode 100644 index 00000000000..ba7d0eee5f6 --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js-postgres.dockerfile @@ -0,0 +1,12 @@ +FROM node:20-slim + +COPY ./ ./ + +RUN npm install + +ENV NODE_ENV production +ENV DATABASE postgres + +EXPOSE 8080 + +CMD ["npm", "start"] diff --git a/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile new file mode 100644 index 00000000000..4262ad19953 --- /dev/null +++ b/frameworks/JavaScript/uwebsockets.js/uwebsockets.js.dockerfile @@ -0,0 +1,11 @@ +FROM node:20-slim + +COPY ./ ./ + +RUN npm install + +ENV NODE_ENV production + +EXPOSE 8080 + +CMD ["npm", "start"] From f496311ba17a4725432703059c0d58317f5b651e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gyula=20Bibern=C3=A1th?= <27079815+b-gyula@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:59:22 +0200 Subject: [PATCH 59/62] Java/armeria: /fortunes exposed to test (#9179) Scala/vertx-web-scala-postgres: /json endpoint exposed to test (makes them appear in composite scoring also) --- frameworks/Java/armeria/benchmark_config.json | 1 + .../vertx-web-scala/benchmark_config.json | 1 + .../src/main/scala/vertx/App.scala | 30 ++++++++----------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/frameworks/Java/armeria/benchmark_config.json b/frameworks/Java/armeria/benchmark_config.json index 32cdbd6303f..bdc474dfd9b 100644 --- a/frameworks/Java/armeria/benchmark_config.json +++ b/frameworks/Java/armeria/benchmark_config.json @@ -7,6 +7,7 @@ "db_url": "/db", "query_url": "/queries/", "update_url": "/updates/", + "fortune_url": "/fortunes", "port": 8080, "approach": "Realistic", "classification": "Micro", diff --git a/frameworks/Scala/vertx-web-scala/benchmark_config.json b/frameworks/Scala/vertx-web-scala/benchmark_config.json index d5f73751a49..4a8c4242d34 100755 --- a/frameworks/Scala/vertx-web-scala/benchmark_config.json +++ b/frameworks/Scala/vertx-web-scala/benchmark_config.json @@ -8,6 +8,7 @@ "fortune_url": "/fortunes", "update_url": "/updates?queries=", "plaintext_url": "/plaintext", + "json_url": "/json", "port": 8080, "approach": "Realistic", "classification": "Micro", diff --git a/frameworks/Scala/vertx-web-scala/src/main/scala/vertx/App.scala b/frameworks/Scala/vertx-web-scala/src/main/scala/vertx/App.scala index 469ba0512d6..0f2991c3b47 100644 --- a/frameworks/Scala/vertx-web-scala/src/main/scala/vertx/App.scala +++ b/frameworks/Scala/vertx-web-scala/src/main/scala/vertx/App.scala @@ -26,7 +26,7 @@ import scala.util.{Failure, Sorting, Success, Try} case class Header(name: CharSequence, value: String) class App extends ScalaVerticle { - + import App._ private val HELLO_WORLD = "Hello, world!" private val HELLO_WORLD_BUFFER = Buffer.buffer(HELLO_WORLD, "UTF-8") private val SERVER = "vert.x" @@ -116,8 +116,7 @@ class App extends ScalaVerticle { .end(World(row.getInteger(0), row.getInteger(1)).encode()) } } else { - App.logger.error("Failed to handle request", ar.cause()) - request.response.setStatusCode(500).end(ar.cause.getMessage) + sendError(request, ar.cause, "Failed to handle Db request") } } ) @@ -136,7 +135,7 @@ class App extends ScalaVerticle { if (!failed) { if (ar.failed) { failed = true - request.response.setStatusCode(500).end(ar.cause.getMessage) + sendError(request, ar.cause, "Failed to handle Queries request") return } // we need a final reference @@ -155,11 +154,6 @@ class App extends ScalaVerticle { } private def handleUpdates(request: HttpServerRequest): Unit = { - def sendError(err: Throwable): Unit = { - App.logger.error("", err) - request.response.setStatusCode(500).end(err.getMessage) - } - def handleUpdates(conn: SqlConnection, worlds: Array[World]): Unit = { Sorting.quickSort(worlds) @@ -170,7 +164,7 @@ class App extends ScalaVerticle { batch, (ar: AsyncResult[RowSet[Row]]) => { if (ar.failed) { - sendError(ar.cause) + sendError(request, ar.cause, "handleUpdates: failed to update DB") return } @@ -197,7 +191,7 @@ class App extends ScalaVerticle { if (!failed) { if (ar2.failed) { failed = true - sendError(ar2.cause) + sendError(request, ar2.cause, "handleUpdates: failed to read DB") return } worlds(index) = World(ar2.result.iterator.next.getInteger(0), App.randomWorld()) @@ -206,7 +200,6 @@ class App extends ScalaVerticle { } } ) - i += 1 } } @@ -230,9 +223,7 @@ class App extends ScalaVerticle { responseWithHeaders(request.response, contentTypeHtml) .end(html.fortune(fortunes).body) } else { - val err = ar.cause - App.logger.error("", err) - response.setStatusCode(500).end(err.getMessage) + sendError(request, ar.cause, "handleFortunes failed to update DB") } } ) @@ -241,9 +232,9 @@ class App extends ScalaVerticle { object App { val logger: Logger = Logger[App] - + val defaultConfigPath = "src/main/conf/config.json" def main(args: Array[String]): Unit = { - val config = new JsonObject(Files.readString(new File(args(0)).toPath)) + val config = new JsonObject(Files.readString(new File(if(args.length < 1) defaultConfigPath else args(0)).toPath)) val vertx = Vertx.vertx(VertxOptions().setPreferNativeTransport(true)) printConfig(vertx) @@ -299,4 +290,9 @@ object App { logger.info("Event Loop Size: {}", JVertxOptions.DEFAULT_EVENT_LOOP_POOL_SIZE) logger.info("Native transport: {}", vertx.isNativeTransportEnabled) } + + def sendError(request: HttpServerRequest, err: Throwable, msg: String = ""): Unit = { + App.logger.error(msg, err) + request.response.setStatusCode(500).end(err.getMessage) + } } From dbaaefa53c929c51cd571cd923c49c2b47213968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Fri, 2 Aug 2024 17:59:44 +0200 Subject: [PATCH 60/62] Cleanup and upgrade of the Spring implementations to Spring Boot 3.3 (#9167) * Upgrade spring test to Spring Boot 3.3.1 This commit also introduces several refinements: - Upgrade to Java 21 with Liberica JRE - Make Message a top level class - Properly exclude autoconfigurations based on profiles - Use Spring Boot 3.3 executable JAR unpack feature - Remove java options enabled by default - Keep debug symbol in JVM bytecode for parameter name resolution * Upgrade spring-webflux test to Spring Boot 3.3.1 This commit also introduces several refinements - Reactivate the test - Remove unmaintained variants to keep only r2dbc and mongo - Upgrade to Spring Boot 3.3.1 - Upgrade to Java 21 with Liberica JRE - Dependency cleanup - Various related updates - Add JSON and textplain endpoints - Properly exclude autoconfigurations based on profiles - Use Spring Boot 3.3 executable JAR unpack feature - Add -Dreactor.netty.http.server.lastFlushWhenNoRead=true property - Keep debug symbol in JVM bytecode for parameter name resolution --- frameworks/Java/spring-webflux/README.md | 9 -- .../Java/spring-webflux/benchmark_config.json | 67 +------------ frameworks/Java/spring-webflux/config.toml | 45 --------- frameworks/Java/spring-webflux/pom.xml | 50 ++-------- .../spring-webflux-jdbc.dockerfile | 13 --- .../spring-webflux-mongo.dockerfile | 9 +- .../spring-webflux-pgclient.dockerfile | 13 --- .../spring-webflux-rxjdbc.dockerfile | 13 --- .../spring-webflux/spring-webflux.dockerfile | 8 +- .../src/main/java/benchmark/App.java | 39 +------- .../src/main/java/benchmark/DateHandler.java | 19 ---- .../src/main/java/benchmark/PgClients.java | 19 ---- .../src/main/java/benchmark/ServerFilter.java | 21 ++++- .../java/benchmark/config/JdbcConfig.java | 22 ----- .../java/benchmark/config/PgClientConfig.java | 94 ------------------- .../java/benchmark/config/R2dbcConfig.java | 63 ------------- .../benchmark/config/ReactiveMongoConfig.java | 54 ----------- .../java/benchmark/config/RxJdbcConfig.java | 25 ----- .../main/java/benchmark/model/Message.java | 15 +++ .../repository/MongoDbRepository.java | 17 ++-- .../repository/PgClientDbRepository.java | 79 ---------------- .../repository/R2dbcDbRepository.java | 4 +- .../repository/RxJdbcDbRepository.java | 60 ------------ .../java/benchmark/web/WebfluxHandler.java | 23 +++-- .../java/benchmark/web/WebfluxRouter.java | 32 ++----- .../src/main/resources/application.yml | 63 ++----------- frameworks/Java/spring/pom.xml | 7 +- frameworks/Java/spring/spring-jpa.dockerfile | 10 +- .../Java/spring/spring-mongo.dockerfile | 10 +- frameworks/Java/spring/spring.dockerfile | 10 +- .../Java/spring/src/main/java/hello/App.java | 2 +- .../hello/controller/HelloController.java | 15 +-- .../src/main/java/hello/model/Message.java | 15 +++ .../spring/src/main/resources/application.yml | 17 +++- 34 files changed, 148 insertions(+), 814 deletions(-) delete mode 100644 frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile delete mode 100644 frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile delete mode 100644 frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile mode change 100755 => 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/App.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/DateHandler.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/PgClients.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java create mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/model/Message.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/repository/PgClientDbRepository.java delete mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/repository/RxJdbcDbRepository.java create mode 100644 frameworks/Java/spring/src/main/java/hello/model/Message.java diff --git a/frameworks/Java/spring-webflux/README.md b/frameworks/Java/spring-webflux/README.md index 91e18bc9ceb..74297391137 100755 --- a/frameworks/Java/spring-webflux/README.md +++ b/frameworks/Java/spring-webflux/README.md @@ -37,15 +37,6 @@ For mongoDB access, spring-data-mongodb with reactive support is used. See [Mong * [Template rendering test source](src/main/java/benchmark/web/WebfluxRouter.java) -## Versions - -* [Java OpenJDK 10](http://openjdk.java.net/) -* [Spring boot 2.1.0.RELEASE](https://spring.io/projects/spring-boot) -* [Spring data mongodb 2.1.0.RELEASE](https://projects.spring.io/spring-data-mongodb/) -* [reactive-pg-client 0.10.6](https://github.com/reactiverse/reactive-pg-client) -* [rxjava2-jdbc 0.2.0](https://github.com/davidmoten/rxjava2-jdbc) -* [r2dbc-postgresql 1.0.0.BUILD-SNAPSHOT](https://github.com/r2dbc/r2dbc-postgresql) - ## Test URLs ### Plaintext Test diff --git a/frameworks/Java/spring-webflux/benchmark_config.json b/frameworks/Java/spring-webflux/benchmark_config.json index 396e9e22a1c..d3d0746d448 100644 --- a/frameworks/Java/spring-webflux/benchmark_config.json +++ b/frameworks/Java/spring-webflux/benchmark_config.json @@ -2,9 +2,11 @@ "framework": "spring-webflux", "tests": [{ "default": { + "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", "fortune_url": "/fortunes", + "plaintext_url": "/plaintext", "update_url": "/updates?queries=", "port": 8080, "approach": "Realistic", @@ -23,9 +25,11 @@ "versus": "spring" }, "mongo": { + "json_url": "/json", "db_url": "/db", "query_url": "/queries?queries=", "fortune_url": "/fortunes", + "plaintext_url": "/plaintext", "port": 8080, "approach": "Realistic", "classification": "Fullstack", @@ -41,69 +45,6 @@ "display_name": "spring-webflux-mongo", "notes": "", "versus": "spring" - }, - "pgclient": { - "db_url": "/db", - "query_url": "/queries?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "spring", - "language": "Java", - "flavor": "None", - "orm": "Micro", - "platform": "Netty", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "spring-webflux-pgclient", - "notes": "", - "versus": "spring" - }, - "rxjdbc": { - "db_url": "/db", - "query_url": "/queries?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "spring", - "language": "Java", - "flavor": "None", - "orm": "Micro", - "platform": "Netty", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "spring-webflux-rxjdbc", - "notes": "", - "versus": "spring" - }, - "jdbc": { - "db_url": "/db", - "query_url": "/queries?queries=", - "fortune_url": "/fortunes", - "update_url": "/updates?queries=", - "port": 8080, - "approach": "Realistic", - "classification": "Fullstack", - "database": "Postgres", - "framework": "spring", - "language": "Java", - "flavor": "None", - "orm": "Micro", - "platform": "Netty", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "spring-webflux-jdbc", - "notes": "", - "versus": "spring" } }] } diff --git a/frameworks/Java/spring-webflux/config.toml b/frameworks/Java/spring-webflux/config.toml index 0cf76705159..806591a8384 100644 --- a/frameworks/Java/spring-webflux/config.toml +++ b/frameworks/Java/spring-webflux/config.toml @@ -16,36 +16,6 @@ platform = "Netty" webserver = "None" versus = "spring" -[pgclient] -urls.db = "/db" -urls.query = "/queries?queries=" -urls.update = "/updates?queries=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Micro" -platform = "Netty" -webserver = "None" -versus = "spring" - -[jdbc] -urls.db = "/db" -urls.query = "/queries?queries=" -urls.update = "/updates?queries=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Micro" -platform = "Netty" -webserver = "None" -versus = "spring" - [mongo] urls.db = "/db" urls.query = "/queries?queries=" @@ -59,18 +29,3 @@ orm = "Full" platform = "Netty" webserver = "None" versus = "spring" - -[rxjdbc] -urls.db = "/db" -urls.query = "/queries?queries=" -urls.update = "/updates?queries=" -urls.fortune = "/fortunes" -approach = "Realistic" -classification = "Fullstack" -database = "Postgres" -database_os = "Linux" -os = "Linux" -orm = "Micro" -platform = "Netty" -webserver = "None" -versus = "spring" diff --git a/frameworks/Java/spring-webflux/pom.xml b/frameworks/Java/spring-webflux/pom.xml index bec59f53b95..4dd5b09698c 100644 --- a/frameworks/Java/spring-webflux/pom.xml +++ b/frameworks/Java/spring-webflux/pom.xml @@ -8,19 +8,18 @@ benchmark spring-webflux-benchmark - 1.1-SNAPSHOT + 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-parent - 3.3.0 + 3.3.1 - 17 + 21 + 21 UTF-8 - 0.11.4 - 0.2.14 @@ -30,7 +29,11 @@ org.springframework.boot - spring-boot-starter-jdbc + spring-boot-starter-data-r2dbc + + + org.postgresql + r2dbc-postgresql org.springframework.boot @@ -40,38 +43,6 @@ org.springframework.boot spring-boot-starter-data-mongodb-reactive - - org.postgresql - postgresql - - - io.reactiverse - reactive-pg-client - ${pgclient.version} - - - com.github.davidmoten - rxjava2-jdbc - ${rxjava2-jdbc.version} - - - - org.postgresql - r2dbc-postgresql - - - io.r2dbc - r2dbc-pool - - - org.springframework.data - spring-data-r2dbc - - - org.springframework.boot - spring-boot-configuration-processor - true - @@ -84,9 +55,6 @@ org.apache.maven.plugins maven-compiler-plugin - - false - diff --git a/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile deleted file mode 100644 index 7c1daea95f3..00000000000 --- a/frameworks/Java/spring-webflux/spring-webflux-jdbc.dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -WORKDIR /spring -COPY src src -COPY pom.xml pom.xml -RUN mvn package -q - -FROM eclipse-temurin:21.0.3_9-jre-jammy -WORKDIR /spring -COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar - -EXPOSE 8080 - -CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile index d26a7bda983..41eedefa4c6 100644 --- a/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux-mongo.dockerfile @@ -1,13 +1,16 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven +FROM maven:3.9.5-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM eclipse-temurin:21.0.3_9-jre-jammy +FROM bellsoft/liberica-openjre-debian:21 WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar +# See https://docs.spring.io/spring-boot/reference/packaging/efficient.html +RUN java -Djarmode=tools -jar app.jar extract + EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=mongo"] +CMD ["java", "-Dlogging.level.root=OFF", "-Dreactor.netty.http.server.lastFlushWhenNoRead=true", "-jar", "app/app.jar", "--spring.profiles.active=mongo"] \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile deleted file mode 100644 index 2bf38ec11e0..00000000000 --- a/frameworks/Java/spring-webflux/spring-webflux-pgclient.dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -WORKDIR /spring -COPY src src -COPY pom.xml pom.xml -RUN mvn package -q - -FROM eclipse-temurin:21.0.3_9-jre-jammy -WORKDIR /spring -COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar - -EXPOSE 8080 - -CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=pgclient,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile b/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile deleted file mode 100644 index 0e1edfb74a9..00000000000 --- a/frameworks/Java/spring-webflux/spring-webflux-rxjdbc.dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -WORKDIR /spring -COPY src src -COPY pom.xml pom.xml -RUN mvn package -q - -FROM eclipse-temurin:21.0.3_9-jre-jammy -WORKDIR /spring -COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar - -EXPOSE 8080 - -CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=rxjdbc,postgres"] diff --git a/frameworks/Java/spring-webflux/spring-webflux.dockerfile b/frameworks/Java/spring-webflux/spring-webflux.dockerfile index 504fb71cfae..6ff2ed4e537 100644 --- a/frameworks/Java/spring-webflux/spring-webflux.dockerfile +++ b/frameworks/Java/spring-webflux/spring-webflux.dockerfile @@ -1,13 +1,15 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven +FROM maven:3.9.5-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM eclipse-temurin:21.0.3_9-jre-jammy +FROM bellsoft/liberica-openjre-debian:21 WORKDIR /spring COPY --from=maven /spring/target/spring-webflux-benchmark.jar app.jar +# See https://docs.spring.io/spring-boot/reference/packaging/efficient.html +RUN java -Djarmode=tools -jar app.jar extract EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=r2dbc,postgres"] +CMD ["java", "-Dlogging.level.root=OFF", "-Dreactor.netty.http.server.lastFlushWhenNoRead=true", "-jar", "app/app.jar", "--spring.profiles.active=r2dbc"] diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java old mode 100755 new mode 100644 index 9fa3f318361..37ff0a80ff0 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java @@ -1,52 +1,15 @@ package benchmark; -import java.util.concurrent.Executors; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.web.reactive.result.view.MustacheViewResolver; -import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.web.reactive.config.EnableWebFlux; -import org.springframework.web.reactive.config.ViewResolverRegistry; -import org.springframework.web.reactive.config.WebFluxConfigurer; - -import reactor.core.scheduler.Scheduler; -import reactor.core.scheduler.Schedulers; @SpringBootApplication -@EnableWebFlux @EnableScheduling -@EnableConfigurationProperties -public class App implements WebFluxConfigurer { - - @Autowired - private MustacheViewResolver mustacheViewResolver; +public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } - @Bean - ServerFilter serverFilter() { - return new ServerFilter(); - } - - @Bean - DateHandler dateHandler() { - return new DateHandler(); - } - - @Bean - Scheduler ioScheduler() { - return Schedulers.fromExecutor(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2)); - } - - @Override - public void configureViewResolvers(ViewResolverRegistry registry) { - registry.viewResolver(mustacheViewResolver); - } - } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/DateHandler.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/DateHandler.java deleted file mode 100644 index fdaab4a2209..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/DateHandler.java +++ /dev/null @@ -1,19 +0,0 @@ -package benchmark; - -import org.springframework.scheduling.annotation.Scheduled; - -import java.util.Date; - -public class DateHandler { - - private Date date = new Date(); - - @Scheduled(fixedRate = 1000) - public void update() { - this.date = new Date(); - } - - public Date getDate() { - return date; - } -} diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/PgClients.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/PgClients.java deleted file mode 100644 index 902478447c6..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/PgClients.java +++ /dev/null @@ -1,19 +0,0 @@ -package benchmark; - -import io.reactiverse.pgclient.PgClient; - -import java.util.Collection; -import java.util.Iterator; -import java.util.stream.Stream; - -public class PgClients { - private final Iterator iterator; - - public PgClients(Collection clients) { - iterator = Stream.generate(() -> clients).flatMap(Collection::stream).iterator(); - } - - public synchronized PgClient getOne() { - return iterator.next(); - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java index 40cc32ff9a7..685ac39e6ad 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java @@ -1,20 +1,35 @@ -package benchmark; +package benchmark.web; import io.netty.handler.codec.http.HttpHeaderNames; import org.springframework.http.HttpHeaders; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; +@Component public class ServerFilter implements WebFilter { + private static final String SERVER_NAME = "spring-webflux"; + private String date; + + public ServerFilter() { + updateDate(); + } + + @Scheduled(fixedRate = 1000) + public void updateDate() { + this.date = java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(java.time.ZonedDateTime.now()); + } + @Override public Mono filter(ServerWebExchange exchange, WebFilterChain chain) { HttpHeaders headers = exchange.getResponse().getHeaders(); headers.add(HttpHeaderNames.SERVER.toString(), SERVER_NAME); - headers.add(HttpHeaderNames.DATE.toString(), java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME.format(java.time.ZonedDateTime.now())); + headers.add(HttpHeaderNames.DATE.toString(), this.date); return chain.filter(exchange); } -} +} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java deleted file mode 100644 index d99729490a4..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/JdbcConfig.java +++ /dev/null @@ -1,22 +0,0 @@ -package benchmark.config; - -import com.zaxxer.hikari.HikariDataSource; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -import javax.sql.DataSource; - -@Configuration -@Profile("jdbc") -public class JdbcConfig { - - @Bean - DataSource datasource(DataSourceProperties dataSourceProperties) { - HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build(); - dataSource.setMaximumPoolSize(Runtime.getRuntime().availableProcessors() * 2); - - return dataSource; - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java deleted file mode 100644 index 9ebf6db60c9..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/PgClientConfig.java +++ /dev/null @@ -1,94 +0,0 @@ -package benchmark.config; - -import benchmark.PgClients; -import io.reactiverse.pgclient.PgClient; -import io.reactiverse.pgclient.PgPool; -import io.reactiverse.pgclient.PgPoolOptions; -import io.vertx.core.Vertx; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -import java.util.ArrayList; -import java.util.List; - -@Configuration -@Profile("pgclient") -@ConfigurationProperties(prefix = "database") -public class PgClientConfig { - private String name; - private String host; - private int port; - private String username; - private String password; - - @Bean - Vertx vertx() { - return Vertx.vertx(); - } - - @Bean - PgClients pgClients(Vertx vertx) { - List clients = new ArrayList<>(); - - for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) { - clients.add(pgClient(vertx)); - } - - return new PgClients(clients); - } - - - public PgPool pgClient(Vertx vertx) { - PgPoolOptions options = new PgPoolOptions(); - options.setDatabase(name); - options.setHost(host); - options.setPort(port); - options.setUser(username); - options.setPassword(password); - options.setCachePreparedStatements(true); - options.setMaxSize(1); - return PgClient.pool(vertx, options); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java deleted file mode 100644 index 5a0de452252..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/R2dbcConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -package benchmark.config; - - -import io.r2dbc.spi.ConnectionFactories; -import io.r2dbc.spi.ConnectionFactory; - -import io.r2dbc.spi.ConnectionFactoryOptions; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.r2dbc.core.DatabaseClient; - -import static io.r2dbc.spi.ConnectionFactoryOptions.*; - -@Configuration -@Profile("r2dbc") -@ConfigurationProperties(prefix = "database") -public class R2dbcConfig { - private String name; - private String host; - private int port; - private String username; - private String password; - - public void setName(String name) { - this.name = name; - } - - public void setHost(String host) { - this.host = host; - } - - public void setPort(int port) { - this.port = port; - } - - public void setUsername(String username) { - this.username = username; - } - - public void setPassword(String password) { - this.password = password; - } - - @Bean - ConnectionFactory connectionFactory() { - return ConnectionFactories.get(ConnectionFactoryOptions.builder() - .option(DRIVER,"pool") - .option(PROTOCOL,"postgresql") - .option(HOST, host) - .option(PORT, port) - .option(USER, username) - .option(PASSWORD, password) - .option(DATABASE, name) - .build()); - } - - @Bean - DatabaseClient databaseClient(ConnectionFactory connectionFactory) { - return DatabaseClient.create(connectionFactory); - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java deleted file mode 100644 index e12178be400..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/ReactiveMongoConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package benchmark.config; - -import com.mongodb.reactivestreams.client.MongoClient; -import com.mongodb.reactivestreams.client.MongoClients; -import org.slf4j.LoggerFactory; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; -import org.springframework.data.mongodb.core.ReactiveMongoTemplate; -import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; - -@Configuration -@EnableReactiveMongoRepositories -@Profile("mongo") -@ConfigurationProperties(prefix = "database") -public class ReactiveMongoConfig extends AbstractReactiveMongoConfiguration { - private String url; - private String name; - - @Override - @Bean - public MongoClient reactiveMongoClient() { - LoggerFactory.getLogger(getClass()).info("Connecting to mongo url: {}/{}", url, name); - return MongoClients.create(url); - } - - @Override - protected String getDatabaseName() { - return name; - } - - @Bean - ReactiveMongoTemplate reactiveMongoTemplate() { - return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName()); - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java deleted file mode 100644 index f4f5916252d..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/config/RxJdbcConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package benchmark.config; - -import org.davidmoten.rx.jdbc.ConnectionProvider; -import org.davidmoten.rx.jdbc.Database; -import org.davidmoten.rx.jdbc.pool.NonBlockingConnectionPool; -import org.davidmoten.rx.jdbc.pool.Pools; -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; - -@Configuration -@Profile("rxjdbc") -public class RxJdbcConfig { - @Bean - Database database(DataSourceProperties dsProps) { - NonBlockingConnectionPool pool = - Pools.nonBlocking() - .maxPoolSize(Runtime.getRuntime().availableProcessors() * 2) - .connectionProvider(ConnectionProvider.from(dsProps.getUrl(), dsProps.getUsername(), dsProps.getPassword())) - .build(); - - return Database.from(pool); - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/model/Message.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/model/Message.java new file mode 100644 index 00000000000..8a94c8d3ed1 --- /dev/null +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/model/Message.java @@ -0,0 +1,15 @@ +package benchmark.model; + +public class Message { + + private final String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + +} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/MongoDbRepository.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/MongoDbRepository.java index 7e6b51ff39a..df777dd2d8e 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/MongoDbRepository.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/MongoDbRepository.java @@ -5,7 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Profile; -import org.springframework.data.mongodb.core.ReactiveMongoTemplate; +import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -18,22 +18,21 @@ @Component @Profile("mongo") public class MongoDbRepository implements DbRepository { - private final Logger log = LoggerFactory.getLogger(getClass()); - private final ReactiveMongoTemplate mongoTemplate; - public MongoDbRepository(ReactiveMongoTemplate mongoTemplate) { - this.mongoTemplate = mongoTemplate; + private final ReactiveMongoOperations operations; + + public MongoDbRepository(ReactiveMongoOperations operations) { + this.operations = operations; } @Override public Mono getWorld(int id) { - log.debug("getWorld({})", id); - return mongoTemplate.findById(id, World.class); + return operations.findById(id, World.class); } @Override public Mono findAndUpdateWorld(int id, int randomNumber) { - return mongoTemplate.findAndModify( + return operations.findAndModify( query(where("id").is(id)), update("randomNumber", randomNumber), options().returnNew(true), @@ -42,6 +41,6 @@ public Mono findAndUpdateWorld(int id, int randomNumber) { @Override public Flux fortunes() { - return mongoTemplate.findAll(Fortune.class); + return operations.findAll(Fortune.class); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/PgClientDbRepository.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/PgClientDbRepository.java deleted file mode 100644 index 50dc6286ea1..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/PgClientDbRepository.java +++ /dev/null @@ -1,79 +0,0 @@ -package benchmark.repository; - -import benchmark.PgClients; -import benchmark.model.Fortune; -import benchmark.model.World; -import io.reactiverse.pgclient.PgIterator; -import io.reactiverse.pgclient.Row; -import io.reactiverse.pgclient.Tuple; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -@Component -@Profile("pgclient") -public class PgClientDbRepository implements DbRepository { - private final Logger log = LoggerFactory.getLogger(getClass()); - private final PgClients pgClients; - - public PgClientDbRepository(PgClients pgClients) { - this.pgClients = pgClients; - } - - @Override - public Mono getWorld(int id) { - return Mono.create(sink -> - pgClients.getOne().preparedQuery("SELECT * FROM world WHERE id = $1", Tuple.of(id), ar -> { - if (ar.failed()) { - sink.error(ar.cause()); - } else { - - final Row row = ar.result().iterator().next(); - - World world = new World(row.getInteger(0), row.getInteger(1)); - sink.success(world); - } - })); - } - - private Mono updateWorld(World world) { - return Mono.create(sink -> { - pgClients.getOne().preparedQuery("UPDATE world SET randomnumber = $1 WHERE id = $2", Tuple.of(world.randomnumber, world.id), ar -> { - if (ar.failed()) { - sink.error(ar.cause()); - } else { - sink.success(world); - } - }); - }); - } - - @Override - public Mono findAndUpdateWorld(int id, int randomNumber) { - return getWorld(id).flatMap(world -> { - world.randomnumber = randomNumber; - return updateWorld(world); - }); - } - - @Override - public Flux fortunes() { - return Flux.create(sink -> - pgClients.getOne().preparedQuery("SELECT * FROM fortune", ar -> { - if (ar.failed()) { - sink.error(ar.cause()); - return; - } - - PgIterator resultSet = ar.result().iterator(); - while (resultSet.hasNext()) { - Tuple row = resultSet.next(); - sink.next(new Fortune(row.getInteger(0), row.getString(1))); - } - sink.complete(); - })); - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java index e5915fc05d7..c7cfb89dea4 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/R2dbcDbRepository.java @@ -22,7 +22,7 @@ public Mono getWorld(int id) { return databaseClient .sql("SELECT id, randomnumber FROM world WHERE id = $1") .bind("$1", id) - .map((row, rowMetaData) -> new World(row.get("id", Integer.class), row.get("randomnumber", Integer.class))) + .mapProperties(World.class) .first(); } @@ -48,7 +48,7 @@ public Mono findAndUpdateWorld(int id, int randomNumber) { public Flux fortunes() { return databaseClient .sql("SELECT id, message FROM fortune") - .map((row, rowMetaData) -> new Fortune(row.get("id", Integer.class), row.get("message", String.class))) + .mapProperties(Fortune.class) .all(); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/RxJdbcDbRepository.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/RxJdbcDbRepository.java deleted file mode 100644 index 1d07720f391..00000000000 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/repository/RxJdbcDbRepository.java +++ /dev/null @@ -1,60 +0,0 @@ -package benchmark.repository; - -import benchmark.model.Fortune; -import benchmark.model.World; -import io.reactivex.Flowable; -import org.davidmoten.rx.jdbc.Database; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -@Component -@Profile("rxjdbc") -public class RxJdbcDbRepository implements DbRepository { - private final Database db; - - public RxJdbcDbRepository(Database db) { - this.db = db; - } - - @Override - public Mono getWorld(int id) { - String sql = "SELECT * FROM world WHERE id = ?"; - - Flowable worldFlowable = db.select(sql) - .parameters(id) - .get(rs -> { - World world = new World(rs.getInt("id"), rs.getInt("randomnumber")); - return world; - }); - - return Mono.from(worldFlowable); - } - - public Mono updateWorld(World world) { - String sql = "UPDATE world SET randomnumber = ? WHERE id = ?"; - - Flowable worldFlowable = db.update(sql) - .parameters(world.randomnumber, world.id) - .counts().map(cnt -> world); - return Mono.from(worldFlowable); - } - - public Mono findAndUpdateWorld(int id, int randomNumber) { - return getWorld(id).flatMap(world -> { - world.randomnumber = randomNumber; - return updateWorld(world); - }); - } - - @Override - public Flux fortunes() { - String sql = "SELECT * FROM fortune"; - - Flowable fortuneFlowable = db.select(sql) - .get(rs -> new Fortune(rs.getInt("id"), rs.getString("message"))); - - return Flux.from(fortuneFlowable); - } -} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java index e7fdeafa404..a7516af6636 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java @@ -1,8 +1,16 @@ package benchmark.web; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; + import benchmark.model.Fortune; +import benchmark.model.Message; import benchmark.model.World; import benchmark.repository.DbRepository; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.MediaType; @@ -10,16 +18,11 @@ import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; - import static java.util.Comparator.comparing; @Component public class WebfluxHandler { + private final DbRepository dbRepository; public WebfluxHandler(DbRepository dbRepository) { @@ -29,13 +32,13 @@ public WebfluxHandler(DbRepository dbRepository) { public Mono plaintext(ServerRequest request) { return ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .body(Mono.just("Hello, World!"), String.class); + .bodyValue("Hello, World!"); } public Mono json(ServerRequest request) { return ServerResponse.ok() .contentType(MediaType.APPLICATION_JSON) - .body(Mono.just(Map.of("message", "Hello, World!")), Map.class); + .bodyValue(new Message("Hello, World!")); } public Mono db(ServerRequest request) { @@ -76,7 +79,7 @@ private static int parseQueryCount(Optional maybeTextValue) { public Mono updates(ServerRequest request) { int queries = getQueries(request); - + Mono> worlds = Flux.range(0, queries) .flatMap(i -> dbRepository.findAndUpdateWorld(randomWorldNumber(), randomWorldNumber())) .collectList(); @@ -105,4 +108,4 @@ private static int getQueries(ServerRequest request) { private static int randomWorldNumber() { return 1 + ThreadLocalRandom.current().nextInt(10000); } -} +} \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java index 7d1ad9c881a..061797738c2 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxRouter.java @@ -6,32 +6,18 @@ import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; - @Configuration public class WebfluxRouter { @Bean - RouterFunction route(WebfluxHandler handler) { - return RouterFunctions - .route( - GET("/plaintext"), - handler::plaintext) - .andRoute( - GET("/json"), - handler::json) - .andRoute( - GET("/db"), - handler::db) - .andRoute( - GET("/queries"), - handler::queries) - .andRoute( - GET("/updates"), - handler::updates) - .andRoute( - GET("/fortunes"), - handler::fortunes) - ; + public RouterFunction route(WebfluxHandler handler) { + return RouterFunctions.route() + .GET("/plaintext", handler::plaintext) + .GET("/json", handler::json) + .GET("/db", handler::db) + .GET("/queries", handler::queries) + .GET("/updates", handler::updates) + .GET("/fortunes", handler::fortunes) + .build(); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/resources/application.yml b/frameworks/Java/spring-webflux/src/main/resources/application.yml index d315f4353ee..af7743831e3 100755 --- a/frameworks/Java/spring-webflux/src/main/resources/application.yml +++ b/frameworks/Java/spring-webflux/src/main/resources/application.yml @@ -1,17 +1,3 @@ -spring: - jpa: - open-in-view: false - ---- -spring: - config: - activate: - on-profile: postgres - datasource: - url: jdbc:postgresql://${database.host}:${database.port}/${database.name} - username: ${database.username} - password: ${database.password} - database: name: hello_world host: tfb-database @@ -19,45 +5,17 @@ database: username: benchmarkdbuser password: benchmarkdbpass ---- -spring: - config: - activate: - on-profile: jdbc - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration - - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration - ---- -spring: - config: - activate: - on-profile: pgclient - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration - - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration - ---- -spring: - config: - activate: - on-profile: rxjdbc - autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration - - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration - --- spring: config: activate: on-profile: r2dbc autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + exclude: org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration + r2dbc: + username: ${database.username} + password: ${database.password} + url: r2dbc:postgresql://${database.host}:${database.port}/${database.name} --- spring: @@ -65,10 +23,9 @@ spring: activate: on-profile: mongo autoconfigure: - exclude: - - org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration -database: - url: mongodb://tfb-database:27017/?waitQueueMultiple=200 - name: hello_world \ No newline at end of file + data: + mongodb: + uri: mongodb://tfb-database:27017/?waitQueueMultiple=200 + database: hello_world diff --git a/frameworks/Java/spring/pom.xml b/frameworks/Java/spring/pom.xml index 4e390ebc4f6..9f131b9a23f 100644 --- a/frameworks/Java/spring/pom.xml +++ b/frameworks/Java/spring/pom.xml @@ -11,11 +11,11 @@ org.springframework.boot spring-boot-starter-parent - 3.3.0 + 3.3.1 - 17 + 21 @@ -61,9 +61,6 @@ org.apache.maven.plugins maven-compiler-plugin - - false - diff --git a/frameworks/Java/spring/spring-jpa.dockerfile b/frameworks/Java/spring/spring-jpa.dockerfile index 4af1b98a73f..0598e9c1f28 100644 --- a/frameworks/Java/spring/spring-jpa.dockerfile +++ b/frameworks/Java/spring/spring-jpa.dockerfile @@ -1,15 +1,15 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -RUN mvn -version +FROM maven:3.9.5-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM eclipse-temurin:21.0.3_9-jre-jammy -RUN java -version +FROM bellsoft/liberica-openjre-debian:21 WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar +# See https://docs.spring.io/spring-boot/reference/packaging/efficient.html +RUN java -Djarmode=tools -jar app.jar extract EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseG1GC", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jpa"] +CMD ["java", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app/app.jar", "--spring.profiles.active=jpa"] \ No newline at end of file diff --git a/frameworks/Java/spring/spring-mongo.dockerfile b/frameworks/Java/spring/spring-mongo.dockerfile index 4fa82a28d5d..e700a21cabd 100644 --- a/frameworks/Java/spring/spring-mongo.dockerfile +++ b/frameworks/Java/spring/spring-mongo.dockerfile @@ -1,15 +1,15 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -RUN mvn -version +FROM maven:3.9.5-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM eclipse-temurin:21.0.3_9-jre-jammy -RUN java -version +FROM bellsoft/liberica-openjre-debian:21 WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar +# See https://docs.spring.io/spring-boot/reference/packaging/efficient.html +RUN java -Djarmode=tools -jar app.jar extract EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseG1GC", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=mongo"] +CMD ["java", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app/app.jar", "--spring.profiles.active=mongo"] \ No newline at end of file diff --git a/frameworks/Java/spring/spring.dockerfile b/frameworks/Java/spring/spring.dockerfile index f6f5145477f..0598e9c1f28 100644 --- a/frameworks/Java/spring/spring.dockerfile +++ b/frameworks/Java/spring/spring.dockerfile @@ -1,15 +1,15 @@ -FROM maven:3.9.6-eclipse-temurin-21 as maven -RUN mvn -version +FROM maven:3.9.5-eclipse-temurin-21 as maven WORKDIR /spring COPY src src COPY pom.xml pom.xml RUN mvn package -q -FROM eclipse-temurin:21.0.3_9-jre-jammy -RUN java -version +FROM bellsoft/liberica-openjre-debian:21 WORKDIR /spring COPY --from=maven /spring/target/hello-spring-1.0-SNAPSHOT.jar app.jar +# See https://docs.spring.io/spring-boot/reference/packaging/efficient.html +RUN java -Djarmode=tools -jar app.jar extract EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app.jar", "--spring.profiles.active=jdbc"] +CMD ["java", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app/app.jar", "--spring.profiles.active=jpa"] \ No newline at end of file diff --git a/frameworks/Java/spring/src/main/java/hello/App.java b/frameworks/Java/spring/src/main/java/hello/App.java index 0ab1327f8c4..d0c13e06844 100644 --- a/frameworks/Java/spring/src/main/java/hello/App.java +++ b/frameworks/Java/spring/src/main/java/hello/App.java @@ -14,7 +14,7 @@ import com.zaxxer.hikari.HikariDataSource; -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, MongoRepositoriesAutoConfiguration.class}) +@SpringBootApplication public class App { public static void main(String[] args) { diff --git a/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java b/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java index 3c891567942..5c11b82ac66 100644 --- a/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java +++ b/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java @@ -6,6 +6,7 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; +import hello.model.Message; import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; @@ -31,7 +32,7 @@ public HelloController( this.updateWorldService = updateWorldService; } - @GetMapping(value = "/plaintext") + @GetMapping("/plaintext") String plaintext(HttpServletResponse response) { response.setContentType(MediaType.TEXT_PLAIN_VALUE); return "Hello, World!"; @@ -102,16 +103,4 @@ private static int parseQueryCount(String textValue) { } return Math.min(500, Math.max(1, parsedValue)); } - - static class Message { - private final String message; - - public Message(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - } } diff --git a/frameworks/Java/spring/src/main/java/hello/model/Message.java b/frameworks/Java/spring/src/main/java/hello/model/Message.java new file mode 100644 index 00000000000..4c675c8a162 --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/model/Message.java @@ -0,0 +1,15 @@ +package hello.model; + +public class Message { + + private final String message; + + public Message(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + +} \ No newline at end of file diff --git a/frameworks/Java/spring/src/main/resources/application.yml b/frameworks/Java/spring/src/main/resources/application.yml index 42c14602858..4796669a8e5 100644 --- a/frameworks/Java/spring/src/main/resources/application.yml +++ b/frameworks/Java/spring/src/main/resources/application.yml @@ -1,10 +1,15 @@ --- spring: - threads: - virtual: - enabled: true jpa: open-in-view: false + config: + activate: + on-profile: jdbc + autoconfigure: + exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration + +--- +spring: config: activate: on-profile: jdbc,jpa @@ -25,6 +30,8 @@ spring: config: activate: on-profile: jpa + autoconfigure: + exclude: org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect @@ -33,6 +40,8 @@ spring: config: activate: on-profile: mongo + autoconfigure: + exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration spring.data.mongodb: host: tfb-database @@ -45,4 +54,4 @@ spring: active: jdbc server.server-header: Spring -server.servlet.encoding.force: true \ No newline at end of file +server.servlet.encoding.force: true From 848d6840769d21e4a39eebc7b902e2d05ea04166 Mon Sep 17 00:00:00 2001 From: Andrew McCloskey Date: Fri, 2 Aug 2024 11:59:56 -0400 Subject: [PATCH 61/62] initial commit of vertx-web-kotlin-dsljson benchmark (#9172) * initial commit of vertx-web-kotlin-dsljson benchmark * removed dagger. improved query performance. --- .../vertx-web-kotlin-dsljson/.gitattributes | 9 + .../Kotlin/vertx-web-kotlin-dsljson/README.md | 36 ++ .../benchmark_config.json | 47 +++ .../vertx-web-kotlin-dsljson/build.gradle.kts | 86 +++++ .../configuration/scripts/server.sh | 47 +++ .../gradle.properties | 1 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43504 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../Kotlin/vertx-web-kotlin-dsljson/gradlew | 252 ++++++++++++ .../vertx-web-kotlin-dsljson/gradlew.bat | 94 +++++ .../settings.gradle.kts | 1 + .../main/kotlin/com/example/starter/App.kt | 50 +++ .../com/example/starter/BasicVerticle.kt | 56 +++ .../com/example/starter/PostgresVerticle.kt | 88 +++++ .../example/starter/db/AbstractRepository.kt | 7 + .../example/starter/db/FortuneRepository.kt | 23 ++ .../com/example/starter/db/WorldRepository.kt | 84 ++++ .../starter/handlers/AbstractHandler.kt | 57 +++ .../starter/handlers/DefaultHandler.kt | 15 + .../starter/handlers/FortuneHandler.kt | 57 +++ .../starter/handlers/MessageHandler.kt | 15 + .../example/starter/handlers/WorldHandler.kt | 56 +++ .../example/starter/io/BufferOutputStream.kt | 362 ++++++++++++++++++ .../com/example/starter/io/JsonResource.kt | 15 + .../com/example/starter/models/Fortune.kt | 14 + .../com/example/starter/models/Message.kt | 7 + .../com/example/starter/models/World.kt | 14 + .../example/starter/utils/FutureExtensions.kt | 14 + .../example/starter/utils/JsonExtensions.kt | 19 + .../starter/utils/PeriodicDateResolver.kt | 16 + .../example/starter/utils/RowSetExtensions.kt | 14 + .../starter/utils/ThrowableExtensions.kt | 12 + .../main/resources/http-server-options.json | 6 + .../src/main/resources/log4j2.xml | 13 + .../main/resources/pg-connect-options.json | 15 + ...x-web-kotlin-dsljson-postgresql.dockerfile | 37 ++ .../vertx-web-kotlin-dsljson.dockerfile | 37 ++ 37 files changed, 1683 insertions(+) create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/.gitattributes create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/AbstractRepository.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/log4j2.xml create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile create mode 100644 frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/.gitattributes b/frameworks/Kotlin/vertx-web-kotlin-dsljson/.gitattributes new file mode 100644 index 00000000000..097f9f98d9e --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md b/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md new file mode 100644 index 00000000000..b8ae3f33b30 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/README.md @@ -0,0 +1,36 @@ +# Vert.x-Web Kotlin Dsljson Benchmarking Test + +Vert.x-Web in Kotlin with Dsljson serialization + +The code is written as a realistic server implementation: +- Code is organized logically into packages +- Repositories are created for each database entity to handler all operations pertaining to a specific table +- Handlers map to the logical entities which they serve +- JSON serialization is provided via Dsljson + - Doing this effectively required a custom Vert.x Buffer implementation that also extended OutputStream in order to rely on the efficient Vert.x heap memory pool instead of building a novel implementation. + +## Test URLs + +### JSON + +http://localhost:8080/json + +### PLAINTEXT + +http://localhost:8080/plaintext + +### DB + +http://localhost:8080/db + +### QUERY + +http://localhost:8080/query?queries= + +### UPDATE + +http://localhost:8080/update?queries= + +### FORTUNES + +http://localhost:8080/fortunes diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json new file mode 100644 index 00000000000..445d7e5f319 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/benchmark_config.json @@ -0,0 +1,47 @@ +{ + "framework": "vertx-web-kotlin-dsljson", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "None", + "framework": "vertx-web", + "language": "Kotlin", + "flavor": "None", + "orm": "Raw", + "platform": "Vert.x", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "vertx-web-kotlin-dsljson", + "notes": "", + "versus": "vertx-web" + }, + "postgresql": { + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/updates?queries=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "postgres", + "framework": "vertx-web", + "language": "Kotlin", + "flavor": "None", + "orm": "Raw", + "platform": "Vert.x", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "vertx-web-kotlin-dsljson-postgresql", + "notes": "", + "versus": "vertx-web-postgres" + } + } + ] +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts new file mode 100644 index 00000000000..5131d1b9ec7 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/build.gradle.kts @@ -0,0 +1,86 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + kotlin("jvm") version "1.9.22" + kotlin("kapt") version "1.9.22" + application + id("com.github.johnrengelman.shadow") version "7.1.2" +} + +group = "com.example" +version = "1.0.0-SNAPSHOT" + +repositories { + mavenCentral() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.JVM_21 + } + jvmToolchain(21) +} + +val mainClassName = "com.example.starter.App" + +val vertxVersion = "4.5.9" +val nettyVersion = "4.1.112.Final" +val scramVersion = "2.1" +val dslJsonVersion = "2.0.2" +val htmlFlowVersion = "4.6" +val log4jVersion = "2.23.1" + +application { + mainClass = mainClassName +} + +dependencies { + listOfNotNull( + // Kotlin + kotlin("stdlib-jdk8"), + kotlin("reflect"), + + // Vertx + platform("io.vertx:vertx-stack-depchain:$vertxVersion"), + "io.vertx:vertx-core", + "io.vertx:vertx-web", + "io.vertx:vertx-pg-client", + "io.vertx:vertx-lang-kotlin", + "io.vertx:vertx-lang-kotlin-coroutines", + + // Netty + "io.netty:netty-transport-native-epoll:$nettyVersion:linux-x86_64", + + // Postgres + "com.ongres.scram:client:$scramVersion", + + // dsljson + "com.dslplatform:dsl-json:$dslJsonVersion", + + // HtmlFlow + "com.github.xmlet:htmlflow:$htmlFlowVersion", + + // Logging + "org.apache.logging.log4j:log4j-core:$log4jVersion", + "org.apache.logging.log4j:log4j-api:$log4jVersion", + "org.apache.logging.log4j:log4j-api-kotlin:1.4.0", + "com.lmax:disruptor:4.0.0", + ).map { implementation(it) } + + listOf( + "com.dslplatform:dsl-json:$dslJsonVersion", + "org.apache.logging.log4j:log4j-core:$log4jVersion", + ).map { kapt(it) } +} + +tasks.withType { + archiveClassifier = "fat" + mergeServiceFiles() +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh b/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh new file mode 100644 index 00000000000..80e05662a59 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/configuration/scripts/server.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +NUM_PROCESSORS=$((`grep --count ^processor /proc/cpuinfo`)) + +JVM_OPTS="-server \ + -Xms2G \ + -Xmx2G \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=512m \ + -XX:ReservedCodeCacheSize=512m \ + -XX:MaxInlineLevel=20 \ + -XX:+AlwaysPreTouch \ + -XX:+UseNUMA \ + -Dvertx.disableMetrics=true \ + -Dvertx.disableH2c=true \ + -Dvertx.disableWebsockets=true \ + -Dvertx.flashPolicyHandler=false \ + -Dvertx.threadChecks=false \ + -Dvertx.disableContextTimings=true \ + -Dvertx.disableTCCL=true \ + -Dvertx.disableHttpHeadersValidation=true \ + -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ + -Dio.netty.buffer.checkBounds=false \ + -Dio.netty.buffer.checkAccessible=false \ + -Dtfb.hasDB=false" + +JAR_PATH="./build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar" + +VERTX_ARGS="-instances 1" + +cleanup() { + echo "Caught SIGINT signal. Stopping the Java program..." + if [ ! -z "$JAVA_PID" ]; then + kill -SIGTERM "$JAVA_PID" + wait "$JAVA_PID" + fi + exit 0 +} + +trap cleanup SIGINT + +java $JVM_OPTS -jar $JAR_PATH $VERTX_ARGS & +JAVA_PID=$! + +echo "Server PID: $JAVA_PID" + +wait "$JAVA_PID" diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties new file mode 100644 index 00000000000..f97ebb7d334 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle.properties @@ -0,0 +1 @@ +org.gradle.parallel=true diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..2c3521197d7c4586c843d1d3e9090525f1898cde GIT binary patch literal 43504 zcma&N1CXTcmMvW9vTb(Rwr$&4wr$(C?dmSu>@vG-+vuvg^_??!{yS%8zW-#zn-LkA z5&1^$^{lnmUON?}LBF8_K|(?T0Ra(xUH{($5eN!MR#ZihR#HxkUPe+_R8Cn`RRs(P z_^*#_XlXmGv7!4;*Y%p4nw?{bNp@UZHv1?Um8r6)Fei3p@ClJn0ECfg1hkeuUU@Or zDaPa;U3fE=3L}DooL;8f;P0ipPt0Z~9P0)lbStMS)ag54=uL9ia-Lm3nh|@(Y?B`; zx_#arJIpXH!U{fbCbI^17}6Ri*H<>OLR%c|^mh8+)*h~K8Z!9)DPf zR2h?lbDZQ`p9P;&DQ4F0sur@TMa!Y}S8irn(%d-gi0*WxxCSk*A?3lGh=gcYN?FGl z7D=Js!i~0=u3rox^eO3i@$0=n{K1lPNU zwmfjRVmLOCRfe=seV&P*1Iq=^i`502keY8Uy-WNPwVNNtJFx?IwAyRPZo2Wo1+S(xF37LJZ~%i)kpFQ3Fw=mXfd@>%+)RpYQLnr}B~~zoof(JVm^^&f zxKV^+3D3$A1G;qh4gPVjhrC8e(VYUHv#dy^)(RoUFM?o%W-EHxufuWf(l*@-l+7vt z=l`qmR56K~F|v<^Pd*p~1_y^P0P^aPC##d8+HqX4IR1gu+7w#~TBFphJxF)T$2WEa zxa?H&6=Qe7d(#tha?_1uQys2KtHQ{)Qco)qwGjrdNL7thd^G5i8Os)CHqc>iOidS} z%nFEDdm=GXBw=yXe1W-ShHHFb?Cc70+$W~z_+}nAoHFYI1MV1wZegw*0y^tC*s%3h zhD3tN8b=Gv&rj}!SUM6|ajSPp*58KR7MPpI{oAJCtY~JECm)*m_x>AZEu>DFgUcby z1Qaw8lU4jZpQ_$;*7RME+gq1KySGG#Wql>aL~k9tLrSO()LWn*q&YxHEuzmwd1?aAtI zBJ>P=&$=l1efe1CDU;`Fd+_;&wI07?V0aAIgc(!{a z0Jg6Y=inXc3^n!U0Atk`iCFIQooHqcWhO(qrieUOW8X(x?(RD}iYDLMjSwffH2~tB z)oDgNBLB^AJBM1M^c5HdRx6fBfka`(LD-qrlh5jqH~);#nw|iyp)()xVYak3;Ybik z0j`(+69aK*B>)e_p%=wu8XC&9e{AO4c~O1U`5X9}?0mrd*m$_EUek{R?DNSh(=br# z#Q61gBzEpmy`$pA*6!87 zSDD+=@fTY7<4A?GLqpA?Pb2z$pbCc4B4zL{BeZ?F-8`s$?>*lXXtn*NC61>|*w7J* z$?!iB{6R-0=KFmyp1nnEmLsA-H0a6l+1uaH^g%c(p{iT&YFrbQ$&PRb8Up#X3@Zsk zD^^&LK~111%cqlP%!_gFNa^dTYT?rhkGl}5=fL{a`UViaXWI$k-UcHJwmaH1s=S$4 z%4)PdWJX;hh5UoK?6aWoyLxX&NhNRqKam7tcOkLh{%j3K^4Mgx1@i|Pi&}<^5>hs5 zm8?uOS>%)NzT(%PjVPGa?X%`N2TQCKbeH2l;cTnHiHppPSJ<7y-yEIiC!P*ikl&!B z%+?>VttCOQM@ShFguHVjxX^?mHX^hSaO_;pnyh^v9EumqSZTi+#f&_Vaija0Q-e*| z7ulQj6Fs*bbmsWp{`auM04gGwsYYdNNZcg|ph0OgD>7O}Asn7^Z=eI>`$2*v78;sj-}oMoEj&@)9+ycEOo92xSyY344^ z11Hb8^kdOvbf^GNAK++bYioknrpdN>+u8R?JxG=!2Kd9r=YWCOJYXYuM0cOq^FhEd zBg2puKy__7VT3-r*dG4c62Wgxi52EMCQ`bKgf*#*ou(D4-ZN$+mg&7$u!! z-^+Z%;-3IDwqZ|K=ah85OLwkO zKxNBh+4QHh)u9D?MFtpbl)us}9+V!D%w9jfAMYEb>%$A;u)rrI zuBudh;5PN}_6J_}l55P3l_)&RMlH{m!)ai-i$g)&*M`eN$XQMw{v^r@-125^RRCF0 z^2>|DxhQw(mtNEI2Kj(;KblC7x=JlK$@78`O~>V!`|1Lm-^JR$-5pUANAnb(5}B}JGjBsliK4& zk6y(;$e&h)lh2)L=bvZKbvh@>vLlreBdH8No2>$#%_Wp1U0N7Ank!6$dFSi#xzh|( zRi{Uw%-4W!{IXZ)fWx@XX6;&(m_F%c6~X8hx=BN1&q}*( zoaNjWabE{oUPb!Bt$eyd#$5j9rItB-h*5JiNi(v^e|XKAj*8(k<5-2$&ZBR5fF|JA z9&m4fbzNQnAU}r8ab>fFV%J0z5awe#UZ|bz?Ur)U9bCIKWEzi2%A+5CLqh?}K4JHi z4vtM;+uPsVz{Lfr;78W78gC;z*yTch~4YkLr&m-7%-xc ztw6Mh2d>_iO*$Rd8(-Cr1_V8EO1f*^@wRoSozS) zy1UoC@pruAaC8Z_7~_w4Q6n*&B0AjOmMWa;sIav&gu z|J5&|{=a@vR!~k-OjKEgPFCzcJ>#A1uL&7xTDn;{XBdeM}V=l3B8fE1--DHjSaxoSjNKEM9|U9#m2<3>n{Iuo`r3UZp;>GkT2YBNAh|b z^jTq-hJp(ebZh#Lk8hVBP%qXwv-@vbvoREX$TqRGTgEi$%_F9tZES@z8Bx}$#5eeG zk^UsLBH{bc2VBW)*EdS({yw=?qmevwi?BL6*=12k9zM5gJv1>y#ML4!)iiPzVaH9% zgSImetD@dam~e>{LvVh!phhzpW+iFvWpGT#CVE5TQ40n%F|p(sP5mXxna+Ev7PDwA zamaV4m*^~*xV+&p;W749xhb_X=$|LD;FHuB&JL5?*Y2-oIT(wYY2;73<^#46S~Gx| z^cez%V7x$81}UWqS13Gz80379Rj;6~WdiXWOSsdmzY39L;Hg3MH43o*y8ibNBBH`(av4|u;YPq%{R;IuYow<+GEsf@R?=@tT@!}?#>zIIn0CoyV!hq3mw zHj>OOjfJM3F{RG#6ujzo?y32m^tgSXf@v=J$ELdJ+=5j|=F-~hP$G&}tDZsZE?5rX ztGj`!S>)CFmdkccxM9eGIcGnS2AfK#gXwj%esuIBNJQP1WV~b~+D7PJTmWGTSDrR` zEAu4B8l>NPuhsk5a`rReSya2nfV1EK01+G!x8aBdTs3Io$u5!6n6KX%uv@DxAp3F@{4UYg4SWJtQ-W~0MDb|j-$lwVn znAm*Pl!?Ps&3wO=R115RWKb*JKoexo*)uhhHBncEDMSVa_PyA>k{Zm2(wMQ(5NM3# z)jkza|GoWEQo4^s*wE(gHz?Xsg4`}HUAcs42cM1-qq_=+=!Gk^y710j=66(cSWqUe zklbm8+zB_syQv5A2rj!Vbw8;|$@C!vfNmNV!yJIWDQ>{+2x zKjuFX`~~HKG~^6h5FntRpnnHt=D&rq0>IJ9#F0eM)Y-)GpRjiN7gkA8wvnG#K=q{q z9dBn8_~wm4J<3J_vl|9H{7q6u2A!cW{bp#r*-f{gOV^e=8S{nc1DxMHFwuM$;aVI^ zz6A*}m8N-&x8;aunp1w7_vtB*pa+OYBw=TMc6QK=mbA-|Cf* zvyh8D4LRJImooUaSb7t*fVfih<97Gf@VE0|z>NcBwBQze);Rh!k3K_sfunToZY;f2 z^HmC4KjHRVg+eKYj;PRN^|E0>Gj_zagfRbrki68I^#~6-HaHg3BUW%+clM1xQEdPYt_g<2K+z!$>*$9nQ>; zf9Bei{?zY^-e{q_*|W#2rJG`2fy@{%6u0i_VEWTq$*(ZN37|8lFFFt)nCG({r!q#9 z5VK_kkSJ3?zOH)OezMT{!YkCuSSn!K#-Rhl$uUM(bq*jY? zi1xbMVthJ`E>d>(f3)~fozjg^@eheMF6<)I`oeJYx4*+M&%c9VArn(OM-wp%M<-`x z7sLP1&3^%Nld9Dhm@$3f2}87!quhI@nwd@3~fZl_3LYW-B?Ia>ui`ELg z&Qfe!7m6ze=mZ`Ia9$z|ARSw|IdMpooY4YiPN8K z4B(ts3p%2i(Td=tgEHX z0UQ_>URBtG+-?0E;E7Ld^dyZ;jjw0}XZ(}-QzC6+NN=40oDb2^v!L1g9xRvE#@IBR zO!b-2N7wVfLV;mhEaXQ9XAU+>=XVA6f&T4Z-@AX!leJ8obP^P^wP0aICND?~w&NykJ#54x3_@r7IDMdRNy4Hh;h*!u(Ol(#0bJdwEo$5437-UBjQ+j=Ic>Q2z` zJNDf0yO6@mr6y1#n3)s(W|$iE_i8r@Gd@!DWDqZ7J&~gAm1#~maIGJ1sls^gxL9LLG_NhU!pTGty!TbhzQnu)I*S^54U6Yu%ZeCg`R>Q zhBv$n5j0v%O_j{QYWG!R9W?5_b&67KB$t}&e2LdMvd(PxN6Ir!H4>PNlerpBL>Zvyy!yw z-SOo8caEpDt(}|gKPBd$qND5#a5nju^O>V&;f890?yEOfkSG^HQVmEbM3Ugzu+UtH zC(INPDdraBN?P%kE;*Ae%Wto&sgw(crfZ#Qy(<4nk;S|hD3j{IQRI6Yq|f^basLY; z-HB&Je%Gg}Jt@={_C{L$!RM;$$|iD6vu#3w?v?*;&()uB|I-XqEKqZPS!reW9JkLewLb!70T7n`i!gNtb1%vN- zySZj{8-1>6E%H&=V}LM#xmt`J3XQoaD|@XygXjdZ1+P77-=;=eYpoEQ01B@L*a(uW zrZeZz?HJsw_4g0vhUgkg@VF8<-X$B8pOqCuWAl28uB|@r`19DTUQQsb^pfqB6QtiT z*`_UZ`fT}vtUY#%sq2{rchyfu*pCg;uec2$-$N_xgjZcoumE5vSI{+s@iLWoz^Mf; zuI8kDP{!XY6OP~q5}%1&L}CtfH^N<3o4L@J@zg1-mt{9L`s^z$Vgb|mr{@WiwAqKg zp#t-lhrU>F8o0s1q_9y`gQNf~Vb!F%70f}$>i7o4ho$`uciNf=xgJ>&!gSt0g;M>*x4-`U)ysFW&Vs^Vk6m%?iuWU+o&m(2Jm26Y(3%TL; zA7T)BP{WS!&xmxNw%J=$MPfn(9*^*TV;$JwRy8Zl*yUZi8jWYF>==j~&S|Xinsb%c z2?B+kpet*muEW7@AzjBA^wAJBY8i|#C{WtO_or&Nj2{=6JTTX05}|H>N2B|Wf!*3_ z7hW*j6p3TvpghEc6-wufFiY!%-GvOx*bZrhZu+7?iSrZL5q9}igiF^*R3%DE4aCHZ zqu>xS8LkW+Auv%z-<1Xs92u23R$nk@Pk}MU5!gT|c7vGlEA%G^2th&Q*zfg%-D^=f z&J_}jskj|Q;73NP4<4k*Y%pXPU2Thoqr+5uH1yEYM|VtBPW6lXaetokD0u z9qVek6Q&wk)tFbQ8(^HGf3Wp16gKmr>G;#G(HRBx?F`9AIRboK+;OfHaLJ(P>IP0w zyTbTkx_THEOs%Q&aPrxbZrJlio+hCC_HK<4%f3ZoSAyG7Dn`=X=&h@m*|UYO-4Hq0 z-Bq&+Ie!S##4A6OGoC~>ZW`Y5J)*ouaFl_e9GA*VSL!O_@xGiBw!AF}1{tB)z(w%c zS1Hmrb9OC8>0a_$BzeiN?rkPLc9%&;1CZW*4}CDDNr2gcl_3z+WC15&H1Zc2{o~i) z)LLW=WQ{?ricmC`G1GfJ0Yp4Dy~Ba;j6ZV4r{8xRs`13{dD!xXmr^Aga|C=iSmor% z8hi|pTXH)5Yf&v~exp3o+sY4B^^b*eYkkCYl*T{*=-0HniSA_1F53eCb{x~1k3*`W zr~};p1A`k{1DV9=UPnLDgz{aJH=-LQo<5%+Em!DNN252xwIf*wF_zS^!(XSm(9eoj z=*dXG&n0>)_)N5oc6v!>-bd(2ragD8O=M|wGW z!xJQS<)u70m&6OmrF0WSsr@I%T*c#Qo#Ha4d3COcX+9}hM5!7JIGF>7<~C(Ear^Sn zm^ZFkV6~Ula6+8S?oOROOA6$C&q&dp`>oR-2Ym3(HT@O7Sd5c~+kjrmM)YmgPH*tL zX+znN>`tv;5eOfX?h{AuX^LK~V#gPCu=)Tigtq9&?7Xh$qN|%A$?V*v=&-2F$zTUv z`C#WyIrChS5|Kgm_GeudCFf;)!WH7FI60j^0o#65o6`w*S7R@)88n$1nrgU(oU0M9 zx+EuMkC>(4j1;m6NoGqEkpJYJ?vc|B zOlwT3t&UgL!pX_P*6g36`ZXQ; z9~Cv}ANFnJGp(;ZhS(@FT;3e)0)Kp;h^x;$*xZn*k0U6-&FwI=uOGaODdrsp-!K$Ac32^c{+FhI-HkYd5v=`PGsg%6I`4d9Jy)uW0y%) zm&j^9WBAp*P8#kGJUhB!L?a%h$hJgQrx!6KCB_TRo%9{t0J7KW8!o1B!NC)VGLM5! zpZy5Jc{`r{1e(jd%jsG7k%I+m#CGS*BPA65ZVW~fLYw0dA-H_}O zrkGFL&P1PG9p2(%QiEWm6x;U-U&I#;Em$nx-_I^wtgw3xUPVVu zqSuKnx&dIT-XT+T10p;yjo1Y)z(x1fb8Dzfn8e yu?e%!_ptzGB|8GrCfu%p?(_ zQccdaaVK$5bz;*rnyK{_SQYM>;aES6Qs^lj9lEs6_J+%nIiuQC*fN;z8md>r_~Mfl zU%p5Dt_YT>gQqfr@`cR!$NWr~+`CZb%dn;WtzrAOI>P_JtsB76PYe*<%H(y>qx-`Kq!X_; z<{RpAqYhE=L1r*M)gNF3B8r(<%8mo*SR2hu zccLRZwGARt)Hlo1euqTyM>^!HK*!Q2P;4UYrysje@;(<|$&%vQekbn|0Ruu_Io(w4#%p6ld2Yp7tlA`Y$cciThP zKzNGIMPXX%&Ud0uQh!uQZz|FB`4KGD?3!ND?wQt6!n*f4EmCoJUh&b?;B{|lxs#F- z31~HQ`SF4x$&v00@(P+j1pAaj5!s`)b2RDBp*PB=2IB>oBF!*6vwr7Dp%zpAx*dPr zb@Zjq^XjN?O4QcZ*O+8>)|HlrR>oD*?WQl5ri3R#2?*W6iJ>>kH%KnnME&TT@ZzrHS$Q%LC?n|e>V+D+8D zYc4)QddFz7I8#}y#Wj6>4P%34dZH~OUDb?uP%-E zwjXM(?Sg~1!|wI(RVuxbu)-rH+O=igSho_pDCw(c6b=P zKk4ATlB?bj9+HHlh<_!&z0rx13K3ZrAR8W)!@Y}o`?a*JJsD+twZIv`W)@Y?Amu_u zz``@-e2X}27$i(2=9rvIu5uTUOVhzwu%mNazS|lZb&PT;XE2|B&W1>=B58#*!~D&) zfVmJGg8UdP*fx(>Cj^?yS^zH#o-$Q-*$SnK(ZVFkw+er=>N^7!)FtP3y~Xxnu^nzY zikgB>Nj0%;WOltWIob|}%lo?_C7<``a5hEkx&1ku$|)i>Rh6@3h*`slY=9U}(Ql_< zaNG*J8vb&@zpdhAvv`?{=zDedJ23TD&Zg__snRAH4eh~^oawdYi6A3w8<Ozh@Kw)#bdktM^GVb zrG08?0bG?|NG+w^&JvD*7LAbjED{_Zkc`3H!My>0u5Q}m!+6VokMLXxl`Mkd=g&Xx z-a>m*#G3SLlhbKB!)tnzfWOBV;u;ftU}S!NdD5+YtOjLg?X}dl>7m^gOpihrf1;PY zvll&>dIuUGs{Qnd- zwIR3oIrct8Va^Tm0t#(bJD7c$Z7DO9*7NnRZorrSm`b`cxz>OIC;jSE3DO8`hX955ui`s%||YQtt2 z5DNA&pG-V+4oI2s*x^>-$6J?p=I>C|9wZF8z;VjR??Icg?1w2v5Me+FgAeGGa8(3S z4vg*$>zC-WIVZtJ7}o9{D-7d>zCe|z#<9>CFve-OPAYsneTb^JH!Enaza#j}^mXy1 z+ULn^10+rWLF6j2>Ya@@Kq?26>AqK{A_| zQKb*~F1>sE*=d?A?W7N2j?L09_7n+HGi{VY;MoTGr_)G9)ot$p!-UY5zZ2Xtbm=t z@dpPSGwgH=QtIcEulQNI>S-#ifbnO5EWkI;$A|pxJd885oM+ zGZ0_0gDvG8q2xebj+fbCHYfAXuZStH2j~|d^sBAzo46(K8n59+T6rzBwK)^rfPT+B zyIFw)9YC-V^rhtK`!3jrhmW-sTmM+tPH+;nwjL#-SjQPUZ53L@A>y*rt(#M(qsiB2 zx6B)dI}6Wlsw%bJ8h|(lhkJVogQZA&n{?Vgs6gNSXzuZpEyu*xySy8ro07QZ7Vk1!3tJphN_5V7qOiyK8p z#@jcDD8nmtYi1^l8ml;AF<#IPK?!pqf9D4moYk>d99Im}Jtwj6c#+A;f)CQ*f-hZ< z=p_T86jog%!p)D&5g9taSwYi&eP z#JuEK%+NULWus;0w32-SYFku#i}d~+{Pkho&^{;RxzP&0!RCm3-9K6`>KZpnzS6?L z^H^V*s!8<>x8bomvD%rh>Zp3>Db%kyin;qtl+jAv8Oo~1g~mqGAC&Qi_wy|xEt2iz zWAJEfTV%cl2Cs<1L&DLRVVH05EDq`pH7Oh7sR`NNkL%wi}8n>IXcO40hp+J+sC!W?!krJf!GJNE8uj zg-y~Ns-<~D?yqbzVRB}G>0A^f0!^N7l=$m0OdZuqAOQqLc zX?AEGr1Ht+inZ-Qiwnl@Z0qukd__a!C*CKuGdy5#nD7VUBM^6OCpxCa2A(X;e0&V4 zM&WR8+wErQ7UIc6LY~Q9x%Sn*Tn>>P`^t&idaOEnOd(Ufw#>NoR^1QdhJ8s`h^|R_ zXX`c5*O~Xdvh%q;7L!_!ohf$NfEBmCde|#uVZvEo>OfEq%+Ns7&_f$OR9xsihRpBb z+cjk8LyDm@U{YN>+r46?nn{7Gh(;WhFw6GAxtcKD+YWV?uge>;+q#Xx4!GpRkVZYu zzsF}1)7$?%s9g9CH=Zs+B%M_)+~*j3L0&Q9u7!|+T`^O{xE6qvAP?XWv9_MrZKdo& z%IyU)$Q95AB4!#hT!_dA>4e@zjOBD*Y=XjtMm)V|+IXzjuM;(l+8aA5#Kaz_$rR6! zj>#&^DidYD$nUY(D$mH`9eb|dtV0b{S>H6FBfq>t5`;OxA4Nn{J(+XihF(stSche7$es&~N$epi&PDM_N`As;*9D^L==2Q7Z2zD+CiU(|+-kL*VG+&9!Yb3LgPy?A zm7Z&^qRG_JIxK7-FBzZI3Q<;{`DIxtc48k> zc|0dmX;Z=W$+)qE)~`yn6MdoJ4co;%!`ddy+FV538Y)j(vg}5*k(WK)KWZ3WaOG!8 z!syGn=s{H$odtpqFrT#JGM*utN7B((abXnpDM6w56nhw}OY}0TiTG1#f*VFZr+^-g zbP10`$LPq_;PvrA1XXlyx2uM^mrjTzX}w{yuLo-cOClE8MMk47T25G8M!9Z5ypOSV zAJUBGEg5L2fY)ZGJb^E34R2zJ?}Vf>{~gB!8=5Z) z9y$>5c)=;o0HeHHSuE4U)#vG&KF|I%-cF6f$~pdYJWk_dD}iOA>iA$O$+4%@>JU08 zS`ep)$XLPJ+n0_i@PkF#ri6T8?ZeAot$6JIYHm&P6EB=BiaNY|aA$W0I+nz*zkz_z zkEru!tj!QUffq%)8y0y`T&`fuus-1p>=^hnBiBqD^hXrPs`PY9tU3m0np~rISY09> z`P3s=-kt_cYcxWd{de@}TwSqg*xVhp;E9zCsnXo6z z?f&Sv^U7n4`xr=mXle94HzOdN!2kB~4=%)u&N!+2;z6UYKUDqi-s6AZ!haB;@&B`? z_TRX0%@suz^TRdCb?!vNJYPY8L_}&07uySH9%W^Tc&1pia6y1q#?*Drf}GjGbPjBS zbOPcUY#*$3sL2x4v_i*Y=N7E$mR}J%|GUI(>WEr+28+V z%v5{#e!UF*6~G&%;l*q*$V?&r$Pp^sE^i-0$+RH3ERUUdQ0>rAq2(2QAbG}$y{de( z>{qD~GGuOk559Y@%$?N^1ApVL_a704>8OD%8Y%8B;FCt%AoPu8*D1 zLB5X>b}Syz81pn;xnB}%0FnwazlWfUV)Z-~rZg6~b z6!9J$EcE&sEbzcy?CI~=boWA&eeIa%z(7SE^qgVLz??1Vbc1*aRvc%Mri)AJaAG!p z$X!_9Ds;Zz)f+;%s&dRcJt2==P{^j3bf0M=nJd&xwUGlUFn?H=2W(*2I2Gdu zv!gYCwM10aeus)`RIZSrCK=&oKaO_Ry~D1B5!y0R=%!i2*KfXGYX&gNv_u+n9wiR5 z*e$Zjju&ODRW3phN925%S(jL+bCHv6rZtc?!*`1TyYXT6%Ju=|X;6D@lq$8T zW{Y|e39ioPez(pBH%k)HzFITXHvnD6hw^lIoUMA;qAJ^CU?top1fo@s7xT13Fvn1H z6JWa-6+FJF#x>~+A;D~;VDs26>^oH0EI`IYT2iagy23?nyJ==i{g4%HrAf1-*v zK1)~@&(KkwR7TL}L(A@C_S0G;-GMDy=MJn2$FP5s<%wC)4jC5PXoxrQBFZ_k0P{{s@sz+gX`-!=T8rcB(=7vW}^K6oLWMmp(rwDh}b zwaGGd>yEy6fHv%jM$yJXo5oMAQ>c9j`**}F?MCry;T@47@r?&sKHgVe$MCqk#Z_3S z1GZI~nOEN*P~+UaFGnj{{Jo@16`(qVNtbU>O0Hf57-P>x8Jikp=`s8xWs^dAJ9lCQ z)GFm+=OV%AMVqVATtN@|vp61VVAHRn87}%PC^RAzJ%JngmZTasWBAWsoAqBU+8L8u z4A&Pe?fmTm0?mK-BL9t+{y7o(7jm+RpOhL9KnY#E&qu^}B6=K_dB}*VlSEiC9fn)+V=J;OnN)Ta5v66ic1rG+dGAJ1 z1%Zb_+!$=tQ~lxQrzv3x#CPb?CekEkA}0MYSgx$Jdd}q8+R=ma$|&1a#)TQ=l$1tQ z=tL9&_^vJ)Pk}EDO-va`UCT1m#Uty1{v^A3P~83_#v^ozH}6*9mIjIr;t3Uv%@VeW zGL6(CwCUp)Jq%G0bIG%?{_*Y#5IHf*5M@wPo6A{$Um++Co$wLC=J1aoG93&T7Ho}P z=mGEPP7GbvoG!uD$k(H3A$Z))+i{Hy?QHdk>3xSBXR0j!11O^mEe9RHmw!pvzv?Ua~2_l2Yh~_!s1qS`|0~0)YsbHSz8!mG)WiJE| z2f($6TQtt6L_f~ApQYQKSb=`053LgrQq7G@98#igV>y#i==-nEjQ!XNu9 z~;mE+gtj4IDDNQJ~JVk5Ux6&LCSFL!y=>79kE9=V}J7tD==Ga+IW zX)r7>VZ9dY=V&}DR))xUoV!u(Z|%3ciQi_2jl}3=$Agc(`RPb z8kEBpvY>1FGQ9W$n>Cq=DIpski};nE)`p3IUw1Oz0|wxll^)4dq3;CCY@RyJgFgc# zKouFh!`?Xuo{IMz^xi-h=StCis_M7yq$u) z?XHvw*HP0VgR+KR6wI)jEMX|ssqYvSf*_3W8zVTQzD?3>H!#>InzpSO)@SC8q*ii- z%%h}_#0{4JG;Jm`4zg};BPTGkYamx$Xo#O~lBirRY)q=5M45n{GCfV7h9qwyu1NxOMoP4)jjZMxmT|IQQh0U7C$EbnMN<3)Kk?fFHYq$d|ICu>KbY_hO zTZM+uKHe(cIZfEqyzyYSUBZa8;Fcut-GN!HSA9ius`ltNebF46ZX_BbZNU}}ZOm{M2&nANL9@0qvih15(|`S~z}m&h!u4x~(%MAO$jHRWNfuxWF#B)E&g3ghSQ9|> z(MFaLQj)NE0lowyjvg8z0#m6FIuKE9lDO~Glg}nSb7`~^&#(Lw{}GVOS>U)m8bF}x zVjbXljBm34Cs-yM6TVusr+3kYFjr28STT3g056y3cH5Tmge~ASxBj z%|yb>$eF;WgrcOZf569sDZOVwoo%8>XO>XQOX1OyN9I-SQgrm;U;+#3OI(zrWyow3 zk==|{lt2xrQ%FIXOTejR>;wv(Pb8u8}BUpx?yd(Abh6? zsoO3VYWkeLnF43&@*#MQ9-i-d0t*xN-UEyNKeyNMHw|A(k(_6QKO=nKMCxD(W(Yop zsRQ)QeL4X3Lxp^L%wzi2-WVSsf61dqliPUM7srDB?Wm6Lzn0&{*}|IsKQW;02(Y&| zaTKv|`U(pSzuvR6Rduu$wzK_W-Y-7>7s?G$)U}&uK;<>vU}^^ns@Z!p+9?St1s)dG zK%y6xkPyyS1$~&6v{kl?Md6gwM|>mt6Upm>oa8RLD^8T{0?HC!Z>;(Bob7el(DV6x zi`I)$&E&ngwFS@bi4^xFLAn`=fzTC;aimE^!cMI2n@Vo%Ae-ne`RF((&5y6xsjjAZ zVguVoQ?Z9uk$2ON;ersE%PU*xGO@T*;j1BO5#TuZKEf(mB7|g7pcEA=nYJ{s3vlbg zd4-DUlD{*6o%Gc^N!Nptgay>j6E5;3psI+C3Q!1ZIbeCubW%w4pq9)MSDyB{HLm|k zxv-{$$A*pS@csolri$Ge<4VZ}e~78JOL-EVyrbxKra^d{?|NnPp86!q>t<&IP07?Z z^>~IK^k#OEKgRH+LjllZXk7iA>2cfH6+(e&9ku5poo~6y{GC5>(bRK7hwjiurqAiZ zg*DmtgY}v83IjE&AbiWgMyFbaRUPZ{lYiz$U^&Zt2YjG<%m((&_JUbZcfJ22(>bi5 z!J?<7AySj0JZ&<-qXX;mcV!f~>G=sB0KnjWca4}vrtunD^1TrpfeS^4dvFr!65knK zZh`d;*VOkPs4*-9kL>$GP0`(M!j~B;#x?Ba~&s6CopvO86oM?-? zOw#dIRc;6A6T?B`Qp%^<U5 z19x(ywSH$_N+Io!6;e?`tWaM$`=Db!gzx|lQ${DG!zb1Zl&|{kX0y6xvO1o z220r<-oaS^^R2pEyY;=Qllqpmue|5yI~D|iI!IGt@iod{Opz@*ml^w2bNs)p`M(Io z|E;;m*Xpjd9l)4G#KaWfV(t8YUn@A;nK^#xgv=LtnArX|vWQVuw3}B${h+frU2>9^ z!l6)!Uo4`5k`<<;E(ido7M6lKTgWezNLq>U*=uz&s=cc$1%>VrAeOoUtA|T6gO4>UNqsdK=NF*8|~*sl&wI=x9-EGiq*aqV!(VVXA57 zw9*o6Ir8Lj1npUXvlevtn(_+^X5rzdR>#(}4YcB9O50q97%rW2me5_L=%ffYPUSRc z!vv?Kv>dH994Qi>U(a<0KF6NH5b16enCp+mw^Hb3Xs1^tThFpz!3QuN#}KBbww`(h z7GO)1olDqy6?T$()R7y%NYx*B0k_2IBiZ14&8|JPFxeMF{vW>HF-ViB*%t0;Thq2} z+qP}n=Cp0wwr%5S+qN<7?r+``=l(h0z2`^8j;g2~Q4u?{cIL{JYY%l|iw&YH4FL(8 z1-*E#ANDHi+1f%lMJbRfq*`nG)*#?EJEVoDH5XdfqwR-C{zmbQoh?E zhW!|TvYv~>R*OAnyZf@gC+=%}6N90yU@E;0b_OV#xL9B?GX(D&7BkujjFC@HVKFci zb_>I5e!yuHA1LC`xm&;wnn|3ht3h7|rDaOsh0ePhcg_^Wh8Bq|AGe`4t5Gk(9^F;M z8mFr{uCm{)Uq0Xa$Fw6+da`C4%)M_#jaX$xj;}&Lzc8wTc%r!Y#1akd|6FMf(a4I6 z`cQqS_{rm0iLnhMG~CfDZc96G3O=Tihnv8g;*w?)C4N4LE0m#H1?-P=4{KeC+o}8b zZX)x#(zEysFm$v9W8-4lkW%VJIjM~iQIVW)A*RCO{Oe_L;rQ3BmF*bhWa}!=wcu@# zaRWW{&7~V-e_$s)j!lJsa-J?z;54!;KnU3vuhp~(9KRU2GKYfPj{qA?;#}H5f$Wv-_ zGrTb(EAnpR0*pKft3a}6$npzzq{}ApC&=C&9KoM3Ge@24D^8ZWJDiXq@r{hP=-02& z@Qrn-cbr2YFc$7XR0j7{jAyR;4LLBf_XNSrmd{dV3;ae;fsEjds*2DZ&@#e)Qcc}w zLgkfW=9Kz|eeM$E`-+=jQSt}*kAwbMBn7AZSAjkHUn4n||NBq*|2QPcKaceA6m)g5 z_}3?DX>90X|35eI7?n+>f9+hl5b>#q`2+`FXbOu9Q94UX-GWH;d*dpmSFd~7WM#H2 zvKNxjOtC)U_tx*0(J)eAI8xAD8SvhZ+VRUA?)| zeJjvg9)vi`Qx;;1QP!c_6hJp1=J=*%!>ug}%O!CoSh-D_6LK0JyiY}rOaqSeja&jb#P|DR7 z_JannlfrFeaE$irfrRIiN|huXmQhQUN6VG*6`bzN4Z3!*G?FjN8!`ZTn6Wn4n=Ync z_|Sq=pO7+~{W2}599SfKz@umgRYj6LR9u0*BaHqdEw^i)dKo5HomT9zzB$I6w$r?6 zs2gu*wNOAMK`+5yPBIxSOJpL$@SN&iUaM zQ3%$EQt%zQBNd`+rl9R~utRDAH%7XP@2Z1s=)ks77I(>#FuwydE5>LzFx)8ye4ClM zb*e2i*E$Te%hTKh7`&rQXz;gvm4Dam(r-!FBEcw*b$U%Wo9DIPOwlC5Ywm3WRCM4{ zF42rnEbBzUP>o>MA){;KANhAW7=FKR=DKK&S1AqSxyP;k z;fp_GVuV}y6YqAd)5p=tJ~0KtaeRQv^nvO?*hZEK-qA;vuIo!}Xgec4QGW2ipf2HK z&G&ppF*1aC`C!FR9(j4&r|SHy74IiDky~3Ab)z@9r&vF+Bapx<{u~gb2?*J zSl{6YcZ$&m*X)X?|8<2S}WDrWN3yhyY7wlf*q`n^z3LT4T$@$y``b{m953kfBBPpQ7hT;zs(Nme`Qw@{_pUO0OG zfugi3N?l|jn-Du3Qn{Aa2#6w&qT+oof=YM!Zq~Xi`vlg<;^)Jreeb^x6_4HL-j}sU z1U^^;-WetwPLKMsdx4QZ$haq3)rA#ATpEh{NXto-tOXjCwO~nJ(Z9F%plZ{z(ZW!e zF>nv&4ViOTs58M+f+sGimF^9cB*9b(gAizwyu5|--SLmBOP-uftqVnVBd$f7YrkJ8!jm*QQEQC zEQ+@T*AA1kV@SPF6H5sT%^$$6!e5;#N((^=OA5t}bqIdqf`PiMMFEDhnV#AQWSfLp zX=|ZEsbLt8Sk&wegQU0&kMC|cuY`&@<#r{t2*sq2$%epiTVpJxWm#OPC^wo_4p++U zU|%XFYs+ZCS4JHSRaVET)jV?lbYAd4ouXx0Ka6*wIFBRgvBgmg$kTNQEvs0=2s^sU z_909)3`Ut!m}}@sv<63E@aQx}-!qVdOjSOnAXTh~MKvr$0nr(1Fj-3uS{U6-T9NG1Y(Ua)Nc}Mi< zOBQz^&^v*$BqmTIO^;r@kpaq3n!BI?L{#bw)pdFV&M?D0HKqC*YBxa;QD_4(RlawI z5wBK;7T^4dT7zt%%P<*-M~m?Et;S^tdNgQSn?4$mFvIHHL!`-@K~_Ar4vBnhy{xuy zigp!>UAwPyl!@~(bkOY;un&B~Evy@5#Y&cEmzGm+)L~4o4~|g0uu&9bh8N0`&{B2b zDj2>biRE1`iw}lv!rl$Smn(4Ob>j<{4dT^TfLe-`cm#S!w_9f;U)@aXWSU4}90LuR zVcbw;`2|6ra88#Cjf#u62xq?J)}I)_y{`@hzES(@mX~}cPWI8}SRoH-H;o~`>JWU$ zhLudK3ug%iS=xjv9tnmOdTXcq_?&o30O;(+VmC&p+%+pd_`V}RY4ibQMNE&N5O+hb3bQ8bxk^33Fu4DB2*~t1909gqoutQHx^plq~;@g$d_+rzS0`2;}2UR2h#?p35B=B*f0BZS4ysiWC!kw?4B-dM%m6_BfRbey1Wh? zT1!@>-y=U}^fxH0A`u1)Mz90G6-<4aW^a@l_9L6Y;cd$3<#xIrhup)XLkFi$W&Ohu z8_j~-VeVXDf9b&6aGelt$g*BzEHgzh)KDgII_Y zb$fcY8?XI6-GEGTZVWW%O;njZld)29a_&1QvNYJ@OpFrUH{er@mnh*}326TYAK7_Z zA={KnK_o3QLk|%m@bx3U#^tCChLxjPxMesOc5D4G+&mvp@Clicz^=kQlWp1|+z|V7 zkU#7l61m@^#`1`{+m2L{sZC#j?#>0)2z4}}kqGhB{NX%~+3{5jOyij!e$5-OAs zDvq+>I2(XsY9%NNhNvKiF<%!6t^7&k{L7~FLdkP9!h%=2Kt$bUt(Zwp*&xq_+nco5 zK#5RCM_@b4WBK*~$CsWj!N!3sF>ijS=~$}_iw@vbKaSp5Jfg89?peR@51M5}xwcHW z(@1TK_kq$c4lmyb=aX3-JORe+JmuNkPP=bM*B?};c=_;h2gT-nt#qbriPkpaqoF@q z<)!80iKvTu`T-B3VT%qKO^lfPQ#m5Ei6Y%Fs@%Pt!8yX&C#tL$=|Ma8i?*^9;}Fk> zyzdQQC5YTBO&gx6kB~yhUUT&%q3a3o+zueh>5D7tdByYVcMz@>j!C@Iyg{N1)veYl`SPshuH6Rk=O6pvVrI71rI5*%uU3u81DpD%qmXsbKWMFR@2m4vO_^l6MMbO9a()DcWmYT&?0B_ zuY~tDiQ6*X7;9B*5pj?;xy_B}*{G}LjW*qU&%*QAyt30@-@O&NQTARZ+%VScr>`s^KX;M!p; z?8)|}P}L_CbOn!u(A{c5?g{s31Kn#7i)U@+_KNU-ZyVD$H7rtOjSht8%N(ST-)%r` z63;Hyp^KIm-?D;E-EnpAAWgz2#z{fawTx_;MR7)O6X~*jm*VUkam7>ueT^@+Gb3-Y zN3@wZls8ibbpaoR2xH=$b3x1Ng5Tai=LT2@_P&4JuBQ!r#Py3ew!ZVH4~T!^TcdyC ze#^@k4a(nNe~G+y zI~yXK@1HHWU4pj{gWT6v@$c(x){cLq*KlFeKy?f$_u##)hDu0X_mwL6uKei~oPd9( zRaF_k&w(J3J8b_`F~?0(Ei_pH}U^c&r$uSYawB8Ybs-JZ|&;vKLWX! z|HFZ%-uBDaP*hMcQKf*|j5!b%H40SPD*#{A`kj|~esk@1?q}-O7WyAm3mD@-vHzw( zTSOlO(K9>GW;@?@xSwpk%X3Ui4_Psm;c*HF~RW+q+C#RO_VT5(x!5B#On-W`T|u z>>=t)W{=B-8wWZejxMaBC9sHzBZGv5uz_uu281kxHg2cll_sZBC&1AKD`CYh2vKeW zm#|MMdC}6A&^DX=>_(etx8f}9o}`(G?Y``M?D+aTPJbZqONmSs>y>WSbvs>7PE~cb zjO+1Y)PMi*!=06^$%< z*{b^66BIl{7zKvz^jut7ylDQBt)ba_F*$UkDgJ2gSNfHB6+`OEiz@xs$Tcrl>X4?o zu9~~b&Xl0?w(7lJXu8-9Yh6V|A3f?)1|~+u-q&6#YV`U2i?XIqUw*lc-QTXwuf@8d zSjMe1BhBKY`Mo{$s%Ce~Hv(^B{K%w{yndEtvyYjjbvFY^rn2>C1Lbi!3RV7F>&;zlSDSk}R>{twI}V zA~NK%T!z=^!qbw(OEgsmSj?#?GR&A$0&K>^(?^4iphc3rN_(xXA%joi)k~DmRLEXl zaWmwMolK%@YiyI|HvX{X$*Ei7y+zJ%m{b}$?N7_SN&p+FpeT%4Z_2`0CP=}Y3D-*@ zL|4W4ja#8*%SfkZzn5sfVknpJv&>glRk^oUqykedE8yCgIwCV)fC1iVwMr4hc#KcV!|M-r_N|nQWw@`j+0(Ywct~kLXQ)Qyncmi{Q4`Ur7A{Ep)n`zCtm8D zVX`kxa8Syc`g$6$($Qc-(_|LtQKWZXDrTir5s*pSVmGhk#dKJzCYT?vqA9}N9DGv> zw}N$byrt?Mk*ZZbN5&zb>pv;rU}EH@Rp54)vhZ=330bLvrKPEPu!WqR%yeM3LB!(E zw|J05Y!tajnZ9Ml*-aX&5T8YtuWDq@on)_*FMhz-?m|>RT0~e3OHllrEMthVY(KwQ zu>ijTc4>Xz-q1(g!ESjaZ+C+Zk5FgmF)rFX29_RmU!`7Pw+0}>8xK^=pOxtUDV)ok zw-=p=OvEH&VO3wToRdI!hPHc`qX+_{T_mj!NxcA&xOgkEuvz`-Aa`ZlNv>qnD0`YT1T3USO0ec!%{KE~UOGPJX%I5_rZDGx@|w zVIMsRPP+}^Xxa&{x!q{hY1wat8jDO7YP0(8xHWeEdrd79lUjB8%)v{X1pQu|1dr*y9M&a(J`038}4>lK&K zIM~6wnX{XA?pFHz{hOmEq{oYBnB@56twXqEcFrFqvCy)sH9B{pQ`G50o{W^t&onwY z-l{ur4#8ylPV5YRLD%%j^d0&_WI>0nmfZ8! zaZ&vo@7D`!=?215+Vk181*U@^{U>VyoXh2F&ZNzZx5tDDtlLc)gi2=|o=GC`uaH;< zFuuF?Q9Q`>S#c(~2p|s49RA`3242`2P+)F)t2N!CIrcl^0#gN@MLRDQ2W4S#MXZJO z8<(9P>MvW;rf2qZ$6sHxCVIr0B-gP?G{5jEDn%W#{T#2_&eIjvlVqm8J$*8A#n`5r zs6PuC!JuZJ@<8cFbbP{cRnIZs>B`?`rPWWL*A?1C3QqGEG?*&!*S0|DgB~`vo_xIo z&n_Sa(>6<$P7%Py{R<>n6Jy?3W|mYYoxe5h^b6C#+UoKJ(zl?^WcBn#|7wMI5=?S# zRgk8l-J`oM%GV&jFc)9&h#9mAyowg^v%Fc-7_^ou5$*YvELa!1q>4tHfX7&PCGqW* zu8In~5`Q5qQvMdToE$w+RP^_cIS2xJjghjCTp6Z(za_D<$S;0Xjt?mAE8~Ym{)zfb zV62v9|59XOvR}wEpm~Cnhyr`=JfC$*o15k?T`3s-ZqF6Gy;Gm+_6H$%oJPywWA^Wl zzn$L=N%{VT8DkQba0|2LqGR#O2Pw!b%LV4#Ojcx5`?Cm;+aLpkyZ=!r1z@E}V= z$2v6v%Ai)MMd`@IM&UD!%%(63VH8+m0Ebk<5Du#0=WeK(E<2~3@>8TceT$wy5F52n zRFtY>G9Gp~h#&R92{G{jLruZSNJ4)gNK+zg*$P zW@~Hf>_Do)tvfEAAMKE1nQ=8coTgog&S;wj(s?Xa0!r?UU5#2>18V#|tKvay1Ka53 zl$RxpMqrkv`Sv&#!_u8$8PMken`QL0_sD2)r&dZziefzSlAdKNKroVU;gRJE#o*}w zP_bO{F4g;|t!iroy^xf~(Q5qc8a3<+vBW%VIOQ1!??d;yEn1at1wpt}*n- z0iQtfu}Isw4ZfH~8p~#RQUKwf<$XeqUr-5?8TSqokdHL7tY|47R; z#d+4NS%Cqp>LQbvvAMIhcCX@|HozKXl)%*5o>P2ZegGuOerV&_MeA}|+o-3L!ZNJd z#1xB^(r!IfE~i>*5r{u;pIfCjhY^Oev$Y1MT16w8pJ0?9@&FH*`d;hS=c#F6fq z{mqsHd*xa;>Hg?j80MwZ%}anqc@&s&2v{vHQS68fueNi5Z(VD2eH>jmv4uvE|HEQm z^=b&?1R9?<@=kjtUfm*I!wPf5Xnma(4*DfPk}Es*H$%NGCIM1qt(LSvbl7&tV>e2$ zUqvZOTiwQyxDoxL(mn?n_x%Tre?L&!FYCOy0>o}#DTC3uSPnyGBv*}!*Yv5IV)Bg_t%V+UrTXfr!Q8+eX}ANR*YLzwme7Rl z@q_*fP7wP2AZ(3WG*)4Z(q@)~c{Je&7?w^?&Wy3)v0{TvNQRGle9mIG>$M2TtQ(Vf z3*PV@1mX)}beRTPjoG#&&IO#Mn(DLGp}mn)_0e=9kXDewC8Pk@yo<8@XZjFP-_zic z{mocvT9Eo)H4Oj$>1->^#DbbiJn^M4?v7XbK>co+v=7g$hE{#HoG6ZEat!s~I<^_s zlFee93KDSbJKlv_+GPfC6P8b>(;dlJ5r9&Pc4kC2uR(0{Kjf+SMeUktef``iXD}8` zGufkM9*Sx4>+5WcK#Vqm$g#5z1DUhc_#gLGe4_icSzN5GKr|J&eB)LS;jTXWA$?(k zy?*%U9Q#Y88(blIlxrtKp6^jksNF>-K1?8=pmYAPj?qq}yO5L>_s8CAv=LQMe3J6? zOfWD>Kx_5A4jRoIU}&aICTgdYMqC|45}St;@0~7>Af+uK3vps9D!9qD)1;Y6Fz>4^ zR1X$s{QNZl7l%}Zwo2wXP+Cj-K|^wqZW?)s1WUw_APZLhH55g{wNW3liInD)WHh${ zOz&K>sB*4inVY3m)3z8w!yUz+CKF%_-s2KVr7DpwTUuZjPS9k-em^;>H4*?*B0Bg7 zLy2nfU=ac5N}x1+Tlq^lkNmB~Dj+t&l#fO&%|7~2iw*N!*xBy+ZBQ>#g_;I*+J{W* z=@*15><)Bh9f>>dgQrEhkrr2FEJ;R2rH%`kda8sD-FY6e#7S-<)V*zQA>)Ps)L- zgUuu@5;Ych#jX_KZ+;qEJJbu{_Z9WSsLSo#XqLpCK$gFidk}gddW(9$v}iyGm_OoH ztn$pv81zROq686_7@avq2heXZnkRi4n(3{5jTDO?9iP%u8S4KEqGL?^uBeg(-ws#1 z9!!Y_2Q~D?gCL3MQZO!n$+Wy(Twr5AS3{F7ak2f)Bu0iG^k^x??0}b6l!>Vjp{e*F z8r*(Y?3ZDDoS1G?lz#J4`d9jAEc9YGq1LbpYoFl!W!(j8-33Ey)@yx+BVpDIVyvpZ zq5QgKy>P}LlV?Bgy@I)JvefCG)I69H1;q@{8E8Ytw^s-rC7m5>Q>ZO(`$`9@`49s2)q#{2eN0A?~qS8%wxh%P*99h*Sv` zW_z3<=iRZBQKaDsKw^TfN;6`mRck|6Yt&e$R~tMA0ix;qgw$n~fe=62aG2v0S`7mU zI}gR#W)f+Gn=e3mm*F^r^tcv&S`Rym`X`6K`i8g-a0!p|#69@Bl!*&)QJ9(E7ycxz z)5-m9v`~$N1zszFi^=m%vw}Y{ZyYub!-6^KIY@mwF|W+|t~bZ%@rifEZ-28I@s$C` z>E+k~R1JC-M>8iC_GR>V9f9+uL2wPRATL9bC(sxd;AMJ>v6c#PcG|Xx1N5^1>ISd0 z4%vf-SNOw+1%yQq1YP`>iqq>5Q590_pr?OxS|HbLjx=9~Y)QO37RihG%JrJ^=Nj>g zPTcO$6r{jdE_096b&L;Wm8vcxUVxF0mA%W`aZz4n6XtvOi($ zaL!{WUCh&{5ar=>u)!mit|&EkGY$|YG<_)ZD)I32uEIWwu`R-_ z`FVeKyrx3>8Ep#2~%VVrQ%u#exo!anPe`bc)-M=^IP1n1?L2UQ@# zpNjoq-0+XCfqXS!LwMgFvG$PkX}5^6yxW)6%`S8{r~BA2-c%-u5SE#%mQ~5JQ=o$c z%+qa0udVq9`|=2n=0k#M=yiEh_vp?(tB|{J{EhVLPM^S@f-O*Lgb390BvwK7{wfdMKqUc0uIXKj5>g^z z#2`5^)>T73Eci+=E4n&jl42E@VYF2*UDiWLUOgF#p9`E4&-A#MJLUa&^hB@g7KL+n zr_bz+kfCcLIlAevILckIq~RCwh6dc5@%yN@#f3lhHIx4fZ_yT~o0#3@h#!HCN(rHHC6#0$+1AMq?bY~(3nn{o5g8{*e_#4RhW)xPmK zTYBEntuYd)`?`bzDksI9*MG$=^w!iiIcWg1lD&kM1NF@qKha0fDVz^W7JCam^!AQFxY@7*`a3tfBwN0uK_~YBQ18@^i%=YB}K0Iq(Q3 z=7hNZ#!N@YErE7{T|{kjVFZ+f9Hn($zih;f&q^wO)PJSF`K)|LdT>!^JLf=zXG>>G z15TmM=X`1%Ynk&dvu$Vic!XyFC(c=qM33v&SIl|p+z6Ah9(XQ0CWE^N-LgE#WF6Z+ zb_v`7^Rz8%KKg_@B>5*s-q*TVwu~MCRiXvVx&_3#r1h&L+{rM&-H6 zrcgH@I>0eY8WBX#Qj}Vml+fpv?;EQXBbD0lx%L?E4)b-nvrmMQS^}p_CI3M24IK(f| zV?tWzkaJXH87MBz^HyVKT&oHB;A4DRhZy;fIC-TlvECK)nu4-3s7qJfF-ZZGt7+6C3xZt!ZX4`M{eN|q!y*d^B+cF5W- zc9C|FzL;$bAfh56fg&y0j!PF8mjBV!qA=z$=~r-orU-{0AcQUt4 zNYC=_9(MOWe$Br9_50i#0z!*a1>U6ZvH>JYS9U$kkrCt7!mEUJR$W#Jt5vT?U&LCD zd@)kn%y|rkV|CijnZ((B2=j_rB;`b}F9+E1T46sg_aOPp+&*W~44r9t3AI}z)yUFJ z+}z5E6|oq+oPC3Jli)EPh9)o^B4KUYkk~AU9!g`OvC`a!#Q>JmDiMLTx>96_iDD9h@nW%Je4%>URwYM%5YU1&Dcdulvv3IH3GSrA4$)QjlGwUt6 zsR6+PnyJ$1x{|R=ogzErr~U|X!+b+F8=6y?Yi`E$yjWXsdmxZa^hIqa)YV9ubUqOj&IGY}bk zH4*DEn({py@MG5LQCI;J#6+98GaZYGW-K-&C`(r5#?R0Z){DlY8ZZk}lIi$xG}Q@2 z0LJhzuus-7dLAEpG1Lf+KOxn&NSwO{wn_~e0=}dovX)T(|WRMTqacoW8;A>8tTDr+0yRa+U!LW z!H#Gnf^iCy$tTk3kBBC=r@xhskjf1}NOkEEM4*r+A4`yNAIjz`_JMUI#xTf$+{UA7 zpBO_aJkKz)iaKqRA{8a6AtpdUwtc#Y-hxtZnWz~i(sfjMk`lq|kGea=`62V6y)TMPZw8q}tFDDHrW_n(Z84ZxWvRrntcw;F|Mv4ff9iaM% z4IM{=*zw}vIpbg=9%w&v`sA+a3UV@Rpn<6`c&5h+8a7izP>E@7CSsCv*AAvd-izwU z!sGJQ?fpCbt+LK`6m2Z3&cKtgcElAl){*m0b^0U#n<7?`8ktdIe#ytZTvaZy728o6 z3GDmw=vhh*U#hCo0gb9s#V5(IILXkw>(6a?BFdIb0%3~Y*5FiMh&JWHd2n(|y@?F8 zL$%!)uFu&n+1(6)oW6Hx*?{d~y zBeR)N*Z{7*gMlhMOad#k4gf`37OzEJ&pH?h!Z4#mNNCfnDI@LbiU~&2Gd^q7ix8~Y6$a=B9bK(BaTEO0$Oh=VCkBPwt0 zf#QuB25&2!m7MWY5xV_~sf(0|Y*#Wf8+FQI(sl2wgdM5H7V{aH6|ntE+OcLsTC`u; zeyrlkJgzdIb5=n#SCH)+kjN)rYW7=rppN3Eb;q_^8Zi}6jtL@eZ2XO^w{mCwX(q!t ztM^`%`ndZ5c+2@?p>R*dDNeVk#v>rsn>vEo;cP2Ecp=@E>A#n0!jZACKZ1=D0`f|{ zZnF;Ocp;$j86m}Gt~N+Ch6CJo7+Wzv|nlsXBvm z?St-5Ke&6hbGAWoO!Z2Rd8ARJhOY|a1rm*sOif%Th`*=^jlgWo%e9`3sS51n*>+Mh(9C7g@*mE|r%h*3k6I_uo;C!N z7CVMIX4kbA#gPZf_0%m18+BVeS4?D;U$QC`TT;X zP#H}tMsa=zS6N7n#BA$Fy8#R7vOesiCLM@d1UO6Tsnwv^gb}Q9I}ZQLI?--C8ok&S z9Idy06+V(_aj?M78-*vYBu|AaJ9mlEJpFEIP}{tRwm?G{ag>6u(ReBKAAx zDR6qe!3G88NQP$i99DZ~CW9lzz}iGynvGA4!yL}_9t`l*SZbEL-%N{n$%JgpDHJRn zvh<{AqR7z@ylV`kXdk+uEu-WWAt^=A4n(J=A1e8DpeLzAd;Nl#qlmp#KcHU!8`YJY zvBZy@>WiBZpx*wQ8JzKw?@k}8l99Wo&H>__vCFL}>m~MTmGvae% zPTn9?iR=@7NJ)?e+n-4kx$V#qS4tLpVUX*Je0@`f5LICdxLnph&Vjbxd*|+PbzS(l zBqqMlUeNoo8wL&_HKnM^8{iDI3IdzJAt32UupSr6XXh9KH2LjWD)Pz+`cmps%eHeD zU%i1SbPuSddp6?th;;DfUlxYnjRpd~i7vQ4V`cD%4+a9*!{+#QRBr5^Q$5Ec?gpju zv@dk9;G>d7QNEdRy}fgeA?i=~KFeibDtYffy)^OP?Ro~-X!onDpm+uGpe&6)*f@xJ zE1I3Qh}`1<7aFB@TS#}ee={<#9%1wOL%cuvOd($y4MC2?`1Nin=pVLXPkknn*0kx> z!9XHW${hYEV;r6F#iz7W=fg|a@GY0UG5>>9>$3Bj5@!N{nWDD`;JOdz_ZaZVVIUgH zo+<=+n8VGL*U%M|J$A~#ll__<`y+jL>bv;TpC!&|d=q%E2B|5p=)b-Q+ZrFO%+D_u z4%rc8BmOAO6{n(i(802yZW93?U;K^ZZlo0Gvs7B+<%}R;$%O}pe*Gi;!xP-M73W`k zXLv473Ex_VPcM-M^JO|H>KD;!sEGJ|E}Qepen;yNG2 zXqgD5sjQUDI(XLM+^8ZX1s_(X+PeyQ$Q5RukRt|Kwr-FSnW!^9?OG64UYX1^bU9d8 zJ}8K&UEYG+Je^cThf8W*^RqG07nSCmp*o5Z;#F zS?jochDWX@p+%CZ%dOKUl}q{9)^U@}qkQtA3zBF)`I&zyIKgb{mv)KtZ}?_h{r#VZ z%C+hwv&nB?we0^H+H`OKGw-&8FaF;=ei!tAclS5Q?qH9J$nt+YxdKkbRFLnWvn7GH zezC6<{mK0dd763JlLFqy&Oe|7UXII;K&2pye~yG4jldY~N;M9&rX}m76NsP=R#FEw zt(9h+=m9^zfl=6pH*D;JP~OVgbJkXh(+2MO_^;%F{V@pc2nGn~=U)Qx|JEV-e=vXk zPxA2J<9~IH{}29#X~KW$(1reJv}lc4_1JF31gdev>!CddVhf_62nsr6%w)?IWxz}{ z(}~~@w>c07!r=FZANq4R!F2Qi2?QGavZ{)PCq~X}3x;4ylsd&m;dQe;0GFSn5 zZ*J<=Xg1fEGYYDZ0{Z4}Jh*xlXa}@412nlKSM#@wjMM z*0(k>Gfd1Mj)smUuX}EM6m)811%n5zzr}T?$ZzH~*3b`3q3gHSpA<3cbzTeRDi`SA zT{O)l3%bH(CN0EEF9ph1(Osw5y$SJolG&Db~uL!I3U{X`h(h%^KsL71`2B1Yn z7(xI+Fk?|xS_Y5)x?oqk$xmjG@_+JdErI(q95~UBTvOXTQaJs?lgrC6Wa@d0%O0cC zzvslIeWMo0|C0({iEWX{=5F)t4Z*`rh@-t0ZTMse3VaJ`5`1zeUK0~F^KRY zj2z-gr%sR<(u0@SNEp%Lj38AB2v-+cd<8pKdtRU&8t3eYH#h7qH%bvKup4cnnrN>l z!5fve)~Y5_U9US`uXDFoOtx2gI&Z!t&VPIoqiv>&H(&1;J9b}kZhcOX7EiW*Bujy#MaCl52%NO-l|@2$aRKvZ!YjwpXwC#nA(tJtd1p?jx&U|?&jcb!0MT6oBlWurVRyiSCX?sN3j}d zh3==XK$^*8#zr+U^wk(UkF}bta4bKVgr`elH^az{w(m}3%23;y7dsEnH*pp{HW$Uk zV9J^I9ea7vp_A}0F8qF{>|rj`CeHZ?lf%HImvEJF<@7cgc1Tw%vAUA47{Qe(sP^5M zT=z<~l%*ZjJvObcWtlN?0$b%NdAj&l`Cr|x((dFs-njsj9%IIqoN|Q?tYtJYlRNIu zY(LtC-F14)Og*_V@gjGH^tLV4uN?f^#=dscCFV~a`r8_o?$gj3HrSk=YK2k^UW)sJ z&=a&&JkMkWshp0sto$c6j8f$J!Bsn*MTjC`3cv@l@7cINa!}fNcu(0XF7ZCAYbX|WJIL$iGx8l zGFFQsw}x|i!jOZIaP{@sw0BrV5Z5u!TGe@JGTzvH$}55Gf<;rieZlz+6E1}z_o3m2 z(t;Cp^Geen7iSt)ZVtC`+tzuv^<6--M`^5JXBeeLXV)>2;f7=l%(-4?+<5~;@=Th{1#>rK3+rLn(44TAFS@u(}dunUSYu}~))W*fr` zkBL}3k_@a4pXJ#u*_N|e#1gTqxE&WPsfDa=`@LL?PRR()9^HxG?~^SNmeO#^-5tMw zeGEW&CuX(Uz#-wZOEt8MmF}hQc%14L)0=ebo`e$$G6nVrb)afh!>+Nfa5P;N zCCOQ^NRel#saUVt$Ds0rGd%gkKP2LsQRxq6)g*`-r(FGM!Q51c|9lk!ha8Um3ys1{ zWpT7XDWYshQ{_F!8D8@3hvXhQDw;GlkUOzni&T1>^uD){WH3wRONgjh$u4u7?+$(Y zqTXEF>1aPNZCXP0nJ;zs6_%6;+D&J_|ugcih**y(4ApT`RKAi5>SZe0Bz|+l7z>P14>0ljIH*LhK z@}2O#{?1RNa&!~sEPBvIkm-uIt^Pt#%JnsbJ`-T0%pb ze}d;dzJFu7oQ=i`VHNt%Sv@?7$*oO`Rt*bRNhXh{FArB`9#f%ksG%q?Z`_<19;dBW z5pIoIo-JIK9N$IE1)g8@+4}_`sE7;Lus&WNAJ^H&=4rGjeAJP%Dw!tn*koQ&PrNZw zY88=H7qpHz11f}oTD!0lWO>pMI;i4sauS`%_!zM!n@91sLH#rz1~iEAu#1b%LA zhB}7{1(8{1{V8+SEs=*f=FcRE^;`6Pxm$Hie~|aD~W1BYy#@Y$C?pxJh*cC!T@8C9{xx*T*8P zhbkRk3*6)Zbk%}u>^?ItOhxdmX$j9KyoxxN>NrYGKMkLF4*fLsL_PRjHNNHCyaUHN z7W8yEhf&ag07fc9FD>B{t0#Civsoy0hvVepDREX(NK1LbK0n*>UJp&1FygZMg7T^G z(02BS)g#qMOI{RJIh7}pGNS8WhSH@kG+4n=(8j<+gVfTur)s*hYus70AHUBS2bN6Zp_GOHYxsbg{-Rcet{@0gzE`t$M0_!ZIqSAIW53j+Ln7N~8J zLZ0DOUjp^j`MvX#hq5dFixo^1szoQ=FTqa|@m>9F@%>7OuF9&_C_MDco&-{wfLKNrDMEN4pRUS8-SD6@GP`>_7$;r>dJo>KbeXm>GfQS? zjFS+Y6^%pDCaI0?9(z^ELsAE1`WhbhNv5DJ$Y}~r;>FynHjmjmA{bfDbseZXsKUv`%Fekv)1@f%7ti;B5hhs}5db1dP+P0${1DgKtb(DvN}6H6;0*LP6blg*rpr;Z(7? zrve>M`x6ZI(wtQc4%lO?v5vr{0iTPl&JT!@k-7qUN8b$O9YuItu7zrQ*$?xJIN#~b z#@z|*5z&D7g5>!o(^v+3N?JnJns5O2W4EkF>re*q1uVjgT#6ROP5>Ho)XTJoHDNRC zuLC(Cd_ZM?FAFPoMw;3FM4Ln0=!+vgTYBx2TdXpM@EhDCorzTS6@2`swp4J^9C0)U zq?)H8)=D;i+H`EVYge>kPy8d*AxKl};iumYu^UeM+e_3>O+LY`D4?pD%;Vextj!(; zomJ(u+dR(0m>+-61HTV7!>03vqozyo@uY@Zh^KrW`w7^ENCYh86_P2VC|4}(ilMBe zwa&B|1a7%Qkd>d14}2*_yYr@8-N}^&?LfSwr)C~UUHr)ydENu=?ZHkvoLS~xTiBH= zD%A=OdoC+10l7@rXif~Z#^AvW+4M-(KQBj=Nhgts)>xmA--IJf1jSZF6>@Ns&nmv} zXRk`|`@P5_9W4O-SI|f^DCZ-n*yX@2gf6N)epc~lRWl7QgCyXdx|zr^gy>q`Vwn^y z&r3_zS}N=HmrVtTZhAQS`3$kBmVZDqr4+o(oNok?tqel9kn3;uUerFRti=k+&W{bb zT{ZtEf51Qf+|Jc*@(nyn#U+nr1SFpu4(I7<1a=)M_yPUAcKVF+(vK!|DTL2;P)yG~ zrI*7V)wN_92cM)j`PtAOFz_dO)jIfTeawh2{d@x0nd^#?pDkBTBzr0Oxgmvjt`U^$ zcTPl=iwuen=;7ExMVh7LLFSKUrTiPJpMB&*Ml32>wl} zYn(H0N4+>MCrm2BC4p{meYPafDEXd4yf$i%ylWpC|9%R4XZBUQiha(x%wgQ5iJ?K_wQBRfw z+pYuKoIameAWV7Ex4$PCd>bYD7)A9J`ri&bwTRN*w~7DR0EeLXW|I2()Zkl6vxiw? zFBX){0zT@w_4YUT4~@TXa;nPb^Tu$DJ=vluc~9)mZ}uHd#4*V_eS7)^eZ9oI%Wws_ z`;97^W|?_Z6xHSsE!3EKHPN<3IZ^jTJW=Il{rMmlnR#OuoE6dqOO1KOMpW84ZtDHNn)(pYvs=frO`$X}sY zKY0At$G85&2>B|-{*+B*aqQn&Mqjt*DVH2kdwEm5f}~Xwn9+tPt?EPwh8=8=VWA8rjt*bHEs1FJ92QohQ)Y z4sQH~AzB5!Pisyf?pVa0?L4gthx2;SKlrr?XRU`?Y>RJgUeJn!az#sNF7oDbzksrD zw8)f=f1t*UK&$}_ktf!yf4Rjt{56ffTA{A=9n})E7~iXaQkE+%GW4zqbmlYF(|hE@ z421q9`UQf$uA5yDLx67`=EnSTxdEaG!6C%9_obpb?;u-^QFX% zU1wQ}Li{PeT^fS;&Sk2#$ZM#Zpxrn7jsd<@qhfWy*H)cw9q!I9!fDOCw~4zg zbW`EHsTp9IQUCETUse)!ZmuRICx}0Oe1KVoqdK+u>67A8v`*X*!*_i5`_qTzYRkbYXg#4vT5~A{lK#bA}Oc4ePu5hr-@;i%Z!4Y;-(yR z(1rHYTc7i1h1aipP4DaIY3g2kF#MX{XW7g&zL!39ohO98=eo5nZtq+nz}2E$OZpxx z&OFaOM1O;?mxq+`%k>YS!-=H7BB&WhqSTUC{S!x*k9E zcB;u0I!h%3nEchQwu1GnNkaQxuWnW0D@Xq5j@5WE@E(WlgDU;FLsT*eV|Bh)aH0;~@^yygFj<=+Vu3p)LlF%1AA%y5z-Oh`2 z$RDKk_6r+f#I`8fQ%y#Wx%~de1qkWL2(q^~veLKwht-dIcpt(@lc>`~@mISRIPKPm zD!Za&aX@7dy*CT!&Z7JC1jP2@8+ro8SmlH>_gzRte%ojgiwfd?TR+%Ny0`sp`QRLy zl5TiQkFhIC!2aaJ&=Ua`c9UuOk9GkSFZ}!IGeMZ5MXrL zGtMj`m{(X9+l%=d|L zW2OY?8!_pyhvJ1@O!Chsf6}@3HmKq@)x;CFItPMpkSr@npO&8zMc_O?*|sqkuL^U? zV9+x3vbr|6;Ft0J^J>IH_xpa<{S5K?u-sQWC7FB9YFMwoCKK3WZ*gvO-wAApF`K%#7@1 z^sEj4*%hH`f0@sRDGI|#Dl20o$Z*gttP$q(_?#~2!H9(!d=)I93-3)?e%@$1^*F=t9t&OQ9!p84Z`+y<$yQ9wlamK~Hz2CRpS8dWJfBl@(M2qX!9d_F= zd|4A&U~8dX^M25wyC7$Swa22$G61V;fl{%Q4Lh!t_#=SP(sr_pvQ=wqOi`R)do~QX zk*_gsy75$xoi5XE&h7;-xVECk;DLoO0lJ3|6(Ba~ezi73_SYdCZPItS5MKaGE_1My zdQpx?h&RuoQ7I=UY{2Qf ziGQ-FpR%piffR_4X{74~>Q!=i`)J@T415!{8e`AXy`J#ZK)5WWm3oH?x1PVvcAqE@ zWI|DEUgxyN({@Y99vCJVwiGyx@9)y2jNg`R{$s2o;`4!^6nDX_pb~fTuzf>ZoPV@X zXKe1ehcZ+3dxCB+vikgKz8pvH?>ZzlOEObd{(-aWY;F0XIbuIjSA+!%TNy87a>BoX zsae$}Fcw&+)z@n{Fvzo;SkAw0U*}?unSO)^-+sbpNRjD8&qyfp%GNH;YKdHlz^)4( z;n%`#2Pw&DPA8tc)R9FW7EBR3?GDWhf@0(u3G4ijQV;{qp3B)`Fd}kMV}gB2U%4Sy z3x>YU&`V^PU$xWc4J!OG{Jglti@E3rdYo62K31iu!BU&pdo}S66Ctq{NB<88P92Y9 zTOqX$h6HH_8fKH(I>MEJZl1_2GB~xI+!|BLvN;CnQrjHuh?grzUO7h;1AbzLi|_O= z2S=(0tX#nBjN92gRsv;7`rDCATA!o(ZA}6)+;g;T#+1~HXGFD1@3D#|Ky9!E@)u=h z3@zg3Us0BCYmq(pB`^QTp|RB9!lX*{;7r|Z(^>J+av(0-oUmIdR78c4(q%hP#=R@W ze{;yy$T^8kXr(oC*#NQMZSQlgU)aa=BrZDwpLUk5tm&(AkNt&Gel`=ydcL*<@Ypx{ z2uOxl>2vSY2g3%Si&JU<9D5#{_z{9PzJh=miNH;STk^;5#%8iMRfPe#G~T>^U_zt? zgSE)`UQhb!G$at%yCf5MU)<&(L73(hY3*%qqPbX;`%QDHed3ZaWw^k)8Vjd#ePg@;I&pMe+A18k+S+bou|QX?8eQ`{P-0vrm=uR;Y(bHV>d>Gen4LHILqcm_ z3peDMRE3JMA8wWgPkSthI^K<|8aal38qvIcEgLjHAFB0P#IfqP2y}L>=8eBR}Fm^V*mw2Q4+o=exP@*#=Zs zIqHh@neG)Vy%v4cB1!L}w9J>IqAo}CsqbFPrUVc@;~Ld7t_2IIG=15mT7Itrjq#2~ zqX*&nwZP>vso$6W!#` z-YZ}jhBwQku-Qc>TIMpn%_z~`^u4v3Skyf)KA}V{`dr!Q;3xK1TuGYdl}$sKF^9X!*a-R*Oq1#tLq!W)gO}{q`1HM;oh1-k4FU@8W(qe>P05$+ z`ud2&;4IW4vq8#2yA{G>OH=G+pS_jctJ*BqD$j-MI#avR+<>m-`H1@{3VgKYn2_Ih z0`2_1qUMRuzgj_V^*;5Ax_0s{_3tYR>|$i#c!F7)#`oVGmsD*M2?%930cBSI4Mj>P zTm&JmUrvDXlB%zeA_7$&ogjGK3>SOlV$ct{4)P0k)Kua%*fx9?)_fkvz<(G=F`KCp zE`0j*=FzH$^Y@iUI}MM2Hf#Yr@oQdlJMB5xe0$aGNk%tgex;0)NEuVYtLEvOt{}ti zL`o$K9HnnUnl*;DTGTNiwr&ydfDp@3Y)g5$pcY9l1-9g;yn6SBr_S9MV8Xl+RWgwb zXL%kZLE4#4rUO(Pj484!=`jy74tQxD0Zg>99vvQ}R$7~GW)-0DVJR@$5}drsp3IQG zlrJL}M{+SdWbrO@+g2BY^a}0VdQtuoml`jJ2s6GsG5D@(^$5pMi3$27psEIOe^n=*Nj|Ug7VXN0OrwMrRq&@sR&vdnsRlI%*$vfmJ~)s z^?lstAT$Ked`b&UZ@A6I<(uCHGZ9pLqNhD_g-kj*Sa#0%(=8j}4zd;@!o;#vJ+Bsd z4&K4RIP>6It9Ir)ey?M6Gi6@JzKNg;=jM=$)gs2#u_WhvuTRwm1x2^*!e%l&j02xz zYInQgI$_V7Epzf3*BU~gos}|EurFj8l}hsI(!5yX!~ECL%cnYMS-e<`AKDL%(G)62 zPU;uF1(~(YbH2444JGh58coXT>(*CdEwaFuyvB|%CULgVQesH$ znB`vk3BMP<-QauWOZ0W6xB5y7?tE5cisG|V;bhY^8+*BH1T0ZLbn&gi12|a9Oa%;I zxvaxX_xe3@ng%;4C?zPHQ1v%dbhjA6Sl7w<*)Nr#F{Ahzj}%n9c&!g5HVrlvUO&R2C)_$x6M9 zahficAbeHL2%jILO>Pq&RPPxl;i{K5#O*Yt15AORTCvkjNfJ)LrN4K{sY7>tGuTQ@ z^?N*+xssG&sfp0c$^vV*H)U1O!fTHk8;Q7@42MT@z6UTd^&DKSxVcC-1OLjl7m63& zBb&goU!hes(GF^yc!107bkV6Pr%;A-WWd@DK2;&=zyiK*0i^0@f?fh2c)4&DRSjrI zk!W^=l^JKlPW9US{*yo?_XT@T2Bx+Cm^+r{*5LVcKVw*ll3+)lkebA-4)o z8f5xHWOx0!FDSs4nv@o@>mxTQrOeKzj@5uL`d>mXSp|#{FE54EE_!KtQNq>-G(&5) ztz?xkqPU16A-8@-quJ|SU^ClZ?bJ2kCJPB|6L>NTDYBprw$WcwCH{B z5qlJ6wK_9sT@Kl6G|Q&$gsl@WT>hE;nDAbH#%f1ZwuOkvWLj{qV$m3LF423&l!^iV zhym*>R>Yyens++~6F5+uZQTCz9t~PEW+e?w)XF2g!^^%6k?@Jcu;MG0FG9!T+Gx{Z zK;31y@(J{!-$k4E{5#Sv(2DGy3EZQY}G_*z*G&CZ_J?m&Fg4IBrvPx1w z1zAb3k}6nT?E)HNCi%}aR^?)%w-DcpBR*tD(r_c{QU6V&2vU-j0;{TVDN6los%YJZ z5C(*ZE#kv-BvlGLDf9>EO#RH_jtolA)iRJ>tSfJpF!#DO+tk% zBAKCwVZwO^p)(Rhk2en$XLfWjQQ`ix>K}Ru6-sn8Ih6k&$$y`zQ}}4dj~o@9gX9_= z#~EkchJqd5$**l}~~6mOl(q#GMIcFg&XCKO;$w>!K14 zko1egAORiG{r|8qj*FsN>?7d`han?*MD#xe^)sOqj;o;hgdaVnBH$BM{_73?znS+R z*G2VHM!Jw6#<FfJ-J%-9AuDW$@mc-Eyk~F{Jbvt` zn;(%DbBDnKIYr~|I>ZTvbH@cxUyw%bp*)OSs}lwO^HTJ2M#u5QsPF0?Jv*OVPfdKv z+t$Z5P!~jzZ~Y!d#iP?S{?M_g%Ua0Q)WawbIx+2uYpcf(7Im%W=rAu4dSceo7RZh# zN38=RmwOJQE$qbPXIuO^E`wSeJKCx3Q76irp~QS#19dusEVCWPrKhK9{7cbIMg9U} TZiJi*F`$tkWLn) literal 0 HcmV?d00001 diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..09523c0e549 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew new file mode 100644 index 00000000000..f5feea6d6b1 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat new file mode 100644 index 00000000000..9d21a21834d --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts b/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts new file mode 100644 index 00000000000..a5d0428ce6f --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "vertx-web-kotlin-dsljson-benchmark" diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt new file mode 100644 index 00000000000..03fb0ca2c04 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/App.kt @@ -0,0 +1,50 @@ +package com.example.starter + +import com.example.starter.utils.PeriodicDateResolver +import com.example.starter.utils.block +import io.vertx.core.Vertx +import io.vertx.core.impl.cpu.CpuCoreSensor +import io.vertx.kotlin.core.deploymentOptionsOf +import io.vertx.kotlin.core.vertxOptionsOf +import kotlin.time.Duration.Companion.seconds +import org.apache.logging.log4j.kotlin.Logging + +object App : Logging { + private const val SERVER_NAME = "Vert.x-Web Benchmark" + + @JvmStatic + fun main(args: Array?) { + val numCores = CpuCoreSensor.availableProcessors() + + val vertx = Vertx.vertx( + vertxOptionsOf( + eventLoopPoolSize = numCores, + preferNativeTransport = true, + ) + ) + vertx.exceptionHandler { + logger.error(it) { "Vertx unexpected exception:" } + vertx.close().block(5.seconds) + } + + // Add the SIGINT handler + Runtime.getRuntime().addShutdownHook(Thread { + vertx.close().block(5.seconds) + }) + + // Initialize the periodic date resolver + PeriodicDateResolver.init(vertx) + + // Check the type of test that is being run + val hasDb = System.getProperty("tfb.hasDB")?.toBoolean() ?: false + + vertx.deployVerticle( + { if (hasDb) PostgresVerticle() else BasicVerticle() }, + deploymentOptionsOf( + instances = numCores, + ) + ) + + logger.info("$SERVER_NAME started.") + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt new file mode 100644 index 00000000000..7870a146c78 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/BasicVerticle.kt @@ -0,0 +1,56 @@ +package com.example.starter + +import com.example.starter.handlers.DefaultHandler +import com.example.starter.handlers.MessageHandler +import com.example.starter.io.JsonResource +import com.example.starter.utils.isConnectionReset +import io.vertx.core.AbstractVerticle +import io.vertx.core.Promise +import io.vertx.core.http.HttpServerOptions +import io.vertx.ext.web.Router +import org.apache.logging.log4j.kotlin.Logging + +class BasicVerticle : AbstractVerticle() { + override fun start(startPromise: Promise) { + val defaultHandler = DefaultHandler() + val messageHandler = MessageHandler() + + val router = Router.router(vertx) + + router + .get("/plaintext") + .handler(defaultHandler::plaintext) + + router + .get("/json") + .handler(messageHandler::readDefaultMessage) + + val server = vertx + .createHttpServer(HTTP_SERVER_OPTIONS) + .requestHandler(router) + .exceptionHandler { + if (it.isConnectionReset()) return@exceptionHandler + logger.error(it) { "Exception in HttpServer" } + } + + server + .listen() + .onSuccess { + logger.info { "HTTP server started on port 8080" } + startPromise.complete() + } + .onFailure { + logger.error(it.cause) { "Failed to start" } + startPromise.fail(it.cause) + } + } + + companion object : Logging { + private const val HTTP_SERVER_OPTIONS_RESOURCE = "http-server-options.json" + + private val HTTP_SERVER_OPTIONS: HttpServerOptions by lazy { + val json = JsonResource.of(HTTP_SERVER_OPTIONS_RESOURCE) + HttpServerOptions(json) + } + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt new file mode 100644 index 00000000000..43cba217ec0 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/PostgresVerticle.kt @@ -0,0 +1,88 @@ +package com.example.starter + +import com.example.starter.db.FortuneRepository +import com.example.starter.db.WorldRepository +import com.example.starter.handlers.FortuneHandler +import com.example.starter.handlers.WorldHandler +import com.example.starter.io.JsonResource +import com.example.starter.utils.array +import com.example.starter.utils.isConnectionReset +import io.vertx.core.AbstractVerticle +import io.vertx.core.Future +import io.vertx.core.Promise +import io.vertx.core.http.HttpServerOptions +import io.vertx.ext.web.Router +import io.vertx.pgclient.PgConnectOptions +import io.vertx.pgclient.PgConnection +import org.apache.logging.log4j.kotlin.Logging + +class PostgresVerticle : AbstractVerticle() { + override fun start(startPromise: Promise) { + Future.all( + PgConnection.connect(vertx, PG_CONNECT_OPTIONS), + PgConnection.connect(vertx, PG_CONNECT_OPTIONS), + ) + .onSuccess { cf -> + val pool = cf.array() + + val fortuneHandler = FortuneHandler(FortuneRepository(pool)) + val worldHandler = WorldHandler(WorldRepository(pool)) + + val router = Router.router(vertx) + + router + .get("/fortunes") + .handler(fortuneHandler::templateFortunes) + + router + .get("/db") + .handler(worldHandler::readRandomWorld) + + router + .get("/queries") + .handler(worldHandler::readRandomWorlds) + + router + .get("/updates") + .handler(worldHandler::updateRandomWorlds) + + val server = vertx + .createHttpServer(HTTP_SERVER_OPTIONS) + .requestHandler(router) + .exceptionHandler { + if (it.isConnectionReset()) return@exceptionHandler + logger.error(it) { "Exception in HttpServer" } + } + + server + .listen() + .onSuccess { + logger.info { "HTTP server started on port 8080" } + startPromise.complete() + } + .onFailure { + logger.error(it) { "Failed to start" } + startPromise.fail(it) + } + } + .onFailure { + logger.error(it) { "Failed to start" } + startPromise.fail(it) + } + } + + companion object : Logging { + private const val HTTP_SERVER_OPTIONS_RESOURCE = "http-server-options.json" + private const val PG_CONNECT_OPTIONS_RESOURCE = "pg-connect-options.json" + + private val HTTP_SERVER_OPTIONS: HttpServerOptions by lazy { + val json = JsonResource.of(HTTP_SERVER_OPTIONS_RESOURCE) + HttpServerOptions(json) + } + + private val PG_CONNECT_OPTIONS: PgConnectOptions by lazy { + val json = JsonResource.of(PG_CONNECT_OPTIONS_RESOURCE) + PgConnectOptions(json) + } + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/AbstractRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/AbstractRepository.kt new file mode 100644 index 00000000000..df665df0769 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/AbstractRepository.kt @@ -0,0 +1,7 @@ +package com.example.starter.db + +import io.vertx.pgclient.PgConnection + +abstract class AbstractRepository( + protected val pool: Array +) \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt new file mode 100644 index 00000000000..3bb95576a4d --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/FortuneRepository.kt @@ -0,0 +1,23 @@ +package com.example.starter.db + +import com.example.starter.models.Fortune +import com.example.starter.utils.mapToArray + +import io.vertx.core.Future +import io.vertx.pgclient.PgConnection +import io.vertx.sqlclient.Row + +class FortuneRepository(pool: Array) : AbstractRepository(pool) { + private val selectFortuneQuery = this.pool[0].preparedQuery(SELECT_FORTUNE_SQL) + + fun selectFortunes(): Future> = selectFortuneQuery + .execute() + .map { it.mapToArray(FortuneRepository::map) } + + companion object { + private const val SELECT_FORTUNE_SQL = "SELECT id, message FROM fortune" + + @Suppress("NOTHING_TO_INLINE") + private inline fun map(row: Row): Fortune = Fortune(row.getInteger(0), row.getString(1)) + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt new file mode 100644 index 00000000000..734b486547a --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/db/WorldRepository.kt @@ -0,0 +1,84 @@ +package com.example.starter.db + +import com.example.starter.models.World +import io.vertx.core.Future +import io.vertx.core.Promise +import io.vertx.pgclient.PgConnection +import io.vertx.sqlclient.PreparedQuery +import io.vertx.sqlclient.Row +import io.vertx.sqlclient.RowSet +import io.vertx.sqlclient.Tuple +import io.vertx.sqlclient.impl.ArrayTuple +import io.vertx.sqlclient.impl.SqlClientInternal +import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.atomic.AtomicInteger + +@Suppress("NOTHING_TO_INLINE") +class WorldRepository(pool: Array) : AbstractRepository(pool) { + private val selectWorldQuery = this.pool[0].preparedQuery(SELECT_WORLD_SQL) + private val updateWorldQueries = generateQueries(this.pool[1]) + + fun selectRandomWorld(): Future = selectWorldQuery + .execute(Tuple.of(randomWorld())) + .map { map(it.iterator().next()) } + + fun selectRandomWorlds(numWorlds: Int): Future> { + val promise = Promise.promise>() + val arr = arrayOfNulls(numWorlds) + val count = AtomicInteger(0) + (this.pool[0] as SqlClientInternal).group { c -> + repeat(numWorlds) { + c.preparedQuery(SELECT_WORLD_SQL).execute(Tuple.of(randomWorld())) { ar -> + val index = count.getAndIncrement() + arr[index] = map(ar.result().iterator().next()) + if (index == numWorlds - 1) { + promise.complete(arr as Array) + } + } + } + } + return promise.future() + } + + fun updateRandomWorlds(numWorlds: Int): Future> = selectRandomWorlds(numWorlds) + .flatMap { worlds -> + val params = ArrayTuple(worlds.size * 3) + worlds.forEach { + it.randomNumber = randomWorld() + params.addValue(it.id) + params.addValue(it.randomNumber) + } + worlds.forEach { + params.addValue(it.id) + } + updateWorldQueries[numWorlds - 1].execute(params).map { worlds } + } + + companion object { + private const val SELECT_WORLD_SQL = "SELECT id, randomnumber FROM world WHERE id = $1" + + private inline fun randomWorld(): Int = 1 + ThreadLocalRandom.current().nextInt(10000) + private inline fun map(row: Row): World = World(row.getInteger(0), row.getInteger(1)) + + private fun generateQueries(conn: PgConnection): Array>> { + val arr = arrayOfNulls>>(500) + for (num in 1..500) { + var paramIndex = 1 + val sb = StringBuilder() + sb.append("UPDATE world SET randomnumber = CASE id ") + for (i in 1..num) { + sb.append("WHEN \$$paramIndex THEN \$${paramIndex + 1} ") + paramIndex += 2 + } + sb.append("ELSE randomnumber END WHERE id IN (") + for (i in 1..num) { + sb.append("\$$paramIndex,") + paramIndex += 1 + } + sb[sb.length - 1] = ')' + arr[num - 1] = conn.preparedQuery(sb.toString()) + } + return arr as Array>> + } + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt new file mode 100644 index 00000000000..cb29d630167 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/AbstractHandler.kt @@ -0,0 +1,57 @@ +package com.example.starter.handlers + +import com.example.starter.utils.PeriodicDateResolver +import io.vertx.core.AsyncResult +import io.vertx.core.Handler +import io.vertx.core.MultiMap +import io.vertx.core.http.HttpHeaders +import io.vertx.core.http.HttpServerResponse +import io.vertx.ext.web.RoutingContext + +@Suppress("NOTHING_TO_INLINE") +abstract class AbstractHandler { + protected companion object { + val NULL_HANDLER: Handler>? = null + + const val SOMETHING_WENT_WRONG = "Something went wrong" + + // Headers + val SERVER: CharSequence = HttpHeaders.createOptimized("Vert.x-Web") + val APPLICATION_JSON: CharSequence = HttpHeaders.createOptimized("application/json") + val TEXT_PLAIN: CharSequence = HttpHeaders.createOptimized("text/plain") + val TEXT_HTML: CharSequence = HttpHeaders.createOptimized("text/html; charset=utf-8") + + inline fun MultiMap.common(): MultiMap = this + .add(HttpHeaders.SERVER, SERVER) + .add(HttpHeaders.DATE, PeriodicDateResolver.current) + + inline fun RoutingContext.json(): HttpServerResponse { + val response = this.response() + val headers = response.headers() + headers + .common() + .add(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON) + return response + } + + inline fun RoutingContext.text(): HttpServerResponse { + val response = this.response() + val headers = response.headers() + headers + .common() + .add(HttpHeaders.CONTENT_TYPE, TEXT_PLAIN) + return response + } + + inline fun RoutingContext.html(): HttpServerResponse { + val response = this.response() + val headers = response.headers() + headers + .common() + .add(HttpHeaders.CONTENT_TYPE, TEXT_HTML) + return response + } + + inline fun RoutingContext.error(): Unit = this.text().end(SOMETHING_WENT_WRONG, NULL_HANDLER) + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt new file mode 100644 index 00000000000..8311474177e --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/DefaultHandler.kt @@ -0,0 +1,15 @@ +package com.example.starter.handlers + +import io.vertx.core.buffer.Buffer +import io.vertx.ext.web.RoutingContext + +class DefaultHandler : AbstractHandler() { + fun plaintext(ctx: RoutingContext) { + ctx.text().end(MESSAGE_BUFFER, NULL_HANDLER) + } + + companion object { + private const val MESSAGE = "Hello, World!" + private val MESSAGE_BUFFER = Buffer.buffer(MESSAGE, "UTF-8") + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt new file mode 100644 index 00000000000..5e60c04cfeb --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/FortuneHandler.kt @@ -0,0 +1,57 @@ +package com.example.starter.handlers + +import com.example.starter.db.FortuneRepository +import com.example.starter.models.Fortune +import htmlflow.HtmlFlow +import htmlflow.HtmlView +import io.vertx.ext.web.RoutingContext +import org.apache.logging.log4j.kotlin.Logging + +class FortuneHandler(private val repository: FortuneRepository) : AbstractHandler() { + fun templateFortunes(ctx: RoutingContext) { + repository + .selectFortunes() + .onSuccess { + val updatedFortunes = it.plus(Fortune(0, "Additional fortune added at request time.")) + updatedFortunes.sort() + ctx.html().end(TEMPLATE.render(updatedFortunes), NULL_HANDLER) + } + .onFailure { + logger.error(it) { SOMETHING_WENT_WRONG } + ctx.error() + } + } + + companion object : Logging { + private val TEMPLATE: HtmlView = HtmlFlow + .view { page -> + page + .html() + .head() + .title() + .text("Fortunes") + .`__`() // title + .`__`() // head + .body() + .table() + .tr() + .th().text("id").`__`() + .th().text("message").`__`() + .`__`() // tr + .dynamic> { container, fortunes -> + fortunes.forEach { + container + .tr() + .td().text(it.id.toString()).`__`() + .td().text(it.message).`__`() + .`__`() // tr + } + } + .`__`() // table + .`__`() // body + .`__`() // html + } + .setIndented(false) + .threadSafe() + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt new file mode 100644 index 00000000000..1fa432ef313 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/MessageHandler.kt @@ -0,0 +1,15 @@ +package com.example.starter.handlers + +import com.example.starter.models.Message +import com.example.starter.utils.serialize +import io.vertx.ext.web.RoutingContext + +class MessageHandler : AbstractHandler() { + fun readDefaultMessage(ctx: RoutingContext) { + ctx.json().end(DEFAULT_MESSAGE.serialize(), NULL_HANDLER) + } + + companion object { + private val DEFAULT_MESSAGE = Message("Hello, World!") + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt new file mode 100644 index 00000000000..1226361d71b --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/handlers/WorldHandler.kt @@ -0,0 +1,56 @@ +package com.example.starter.handlers + +import com.example.starter.db.WorldRepository +import com.example.starter.utils.serialize +import io.vertx.ext.web.RoutingContext +import org.apache.logging.log4j.kotlin.Logging + +class WorldHandler(private val repository: WorldRepository) : AbstractHandler() { + fun readRandomWorld(ctx: RoutingContext) { + repository + .selectRandomWorld() + .onSuccess { + ctx.json().end(it.serialize(), NULL_HANDLER) + } + .onFailure { + logger.error(it) { SOMETHING_WENT_WRONG } + ctx.error() + } + } + + fun readRandomWorlds(ctx: RoutingContext) { + val queries = ctx.queries() + repository + .selectRandomWorlds(queries) + .onSuccess { + ctx.json().end(it.serialize(), NULL_HANDLER) + } + .onFailure { + logger.error(it) { SOMETHING_WENT_WRONG } + ctx.error() + } + } + + fun updateRandomWorlds(ctx: RoutingContext) { + val queries = ctx.queries() + repository + .updateRandomWorlds(queries) + .onSuccess { + ctx.json().end(it.serialize(), NULL_HANDLER) + } + .onFailure { + logger.error(it) { SOMETHING_WENT_WRONG } + ctx.error() + } + } + + companion object : Logging { + private const val QUERIES_PARAM_NAME = "queries" + + @Suppress("NOTHING_TO_INLINE") + private inline fun RoutingContext.queries(): Int { + val queriesParam = this.request().getParam(QUERIES_PARAM_NAME) + return queriesParam?.toIntOrNull()?.coerceIn(1, 500) ?: 1 + } + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt new file mode 100644 index 00000000000..d82b31fb6ee --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/BufferOutputStream.kt @@ -0,0 +1,362 @@ +package com.example.starter.io + +import io.netty.buffer.ByteBuf +import io.vertx.core.buffer.Buffer +import io.vertx.core.json.JsonArray +import io.vertx.core.json.JsonObject +import java.io.IOException +import java.io.OutputStream +import java.nio.ByteBuffer +import java.nio.charset.Charset + +class BufferOutputStream(initialSizeHint: Int = 0) : Buffer, OutputStream() { + private val buffer: Buffer = Buffer.buffer(initialSizeHint) + + @Throws(IOException::class) + override fun write(b: Int) { + buffer.appendByte(b.toByte()) + } + + @Throws(IOException::class) + override fun write(bytes: ByteArray) { + buffer.appendBytes(bytes) + } + + @Throws(IOException::class) + override fun write(bytes: ByteArray, offset: Int, len: Int) { + buffer.appendBytes(bytes, offset, len) + } + + override fun toString(enc: String?): String { + return buffer.toString(enc) + } + + override fun toString(enc: Charset?): String { + return buffer.toString(enc) + } + + override fun writeToBuffer(other: Buffer?) { + buffer.writeToBuffer(other) + } + + override fun readFromBuffer(pos: Int, other: Buffer?): Int { + return buffer.readFromBuffer(pos, other) + } + + override fun copy(): Buffer { + return buffer.copy() + } + + override fun toJsonObject(): JsonObject { + return buffer.toJsonObject() + } + + override fun toJsonArray(): JsonArray { + return buffer.toJsonArray() + } + + override fun getByte(pos: Int): Byte { + return buffer.getByte(pos) + } + + override fun getUnsignedByte(pos: Int): Short { + return buffer.getUnsignedByte(pos) + } + + override fun getInt(pos: Int): Int { + return buffer.getInt(pos) + } + + override fun getIntLE(pos: Int): Int { + return buffer.getIntLE(pos) + } + + override fun getUnsignedInt(pos: Int): Long { + return buffer.getUnsignedInt(pos) + } + + override fun getUnsignedIntLE(pos: Int): Long { + return buffer.getUnsignedIntLE(pos) + } + + override fun getLong(pos: Int): Long { + return buffer.getLong(pos) + } + + override fun getLongLE(pos: Int): Long { + return buffer.getLongLE(pos) + } + + override fun getDouble(pos: Int): Double { + return buffer.getDouble(pos) + } + + override fun getFloat(pos: Int): Float { + return buffer.getFloat(pos) + } + + override fun getShort(pos: Int): Short { + return buffer.getShort(pos) + } + + override fun getShortLE(pos: Int): Short { + return buffer.getShortLE(pos) + } + + override fun getUnsignedShort(pos: Int): Int { + return buffer.getUnsignedShort(pos) + } + + override fun getUnsignedShortLE(pos: Int): Int { + return buffer.getUnsignedShortLE(pos) + } + + override fun getMedium(pos: Int): Int { + return buffer.getMedium(pos) + } + + override fun getMediumLE(pos: Int): Int { + return buffer.getMediumLE(pos) + } + + override fun getUnsignedMedium(pos: Int): Int { + return buffer.getUnsignedMedium(pos) + } + + override fun getUnsignedMediumLE(pos: Int): Int { + return buffer.getUnsignedMediumLE(pos) + } + + override fun getBytes(): ByteArray { + return buffer.bytes + } + + override fun getBytes(start: Int, end: Int): ByteArray { + return buffer.getBytes(start, end) + } + + override fun getBytes(dst: ByteArray?): Buffer { + return buffer.getBytes(dst) + } + + override fun getBytes(dst: ByteArray?, dstIndex: Int): Buffer { + return buffer.getBytes(dst, dstIndex) + } + + override fun getBytes(start: Int, end: Int, dst: ByteArray?): Buffer { + return buffer.getBytes(start, end, dst) + } + + override fun getBytes(start: Int, end: Int, dst: ByteArray?, dstIndex: Int): Buffer { + return buffer.getBytes(start, end, dst, dstIndex) + } + + override fun getBuffer(start: Int, end: Int): Buffer { + return buffer.getBuffer(start, end) + } + + override fun getString(start: Int, end: Int, enc: String?): String { + return buffer.getString(start, end, enc) + } + + override fun getString(start: Int, end: Int): String { + return buffer.getString(start, end) + } + + override fun appendBuffer(buff: Buffer?): Buffer { + return buffer.appendBuffer(buff) + } + + override fun appendBuffer(buff: Buffer?, offset: Int, len: Int): Buffer { + return buffer.appendBuffer(buff, offset, len) + } + + override fun appendBytes(bytes: ByteArray?): Buffer { + return buffer.appendBytes(bytes) + } + + override fun appendBytes(bytes: ByteArray?, offset: Int, len: Int): Buffer { + return buffer.appendBytes(bytes, offset, len) + } + + override fun appendByte(b: Byte): Buffer { + return buffer.appendByte(b) + } + + override fun appendUnsignedByte(b: Short): Buffer { + return buffer.appendUnsignedByte(b) + } + + override fun appendInt(i: Int): Buffer { + return buffer.appendInt(i) + } + + override fun appendIntLE(i: Int): Buffer { + return buffer.appendIntLE(i) + } + + override fun appendUnsignedInt(i: Long): Buffer { + return buffer.appendUnsignedInt(i) + } + + override fun appendUnsignedIntLE(i: Long): Buffer { + return buffer.appendUnsignedIntLE(i) + } + + override fun appendMedium(i: Int): Buffer { + return buffer.appendMedium(i) + } + + override fun appendMediumLE(i: Int): Buffer { + return buffer.appendMediumLE(i) + } + + override fun appendLong(l: Long): Buffer { + return buffer.appendLong(l) + } + + override fun appendLongLE(l: Long): Buffer { + return buffer.appendLongLE(l) + } + + override fun appendShort(s: Short): Buffer { + return buffer.appendShort(s) + } + + override fun appendShortLE(s: Short): Buffer { + return buffer.appendShortLE(s) + } + + override fun appendUnsignedShort(s: Int): Buffer { + return buffer.appendUnsignedShort(s) + } + + override fun appendUnsignedShortLE(s: Int): Buffer { + return buffer.appendUnsignedShortLE(s) + } + + override fun appendFloat(f: Float): Buffer { + return buffer.appendFloat(f) + } + + override fun appendDouble(d: Double): Buffer { + return buffer.appendDouble(d) + } + + override fun appendString(str: String?, enc: String?): Buffer { + return buffer.appendString(str, enc) + } + + override fun appendString(str: String?): Buffer { + return buffer.appendString(str) + } + + override fun setByte(pos: Int, b: Byte): Buffer { + return buffer.setByte(pos, b) + } + + override fun setUnsignedByte(pos: Int, b: Short): Buffer { + return buffer.setUnsignedByte(pos, b) + } + + override fun setInt(pos: Int, i: Int): Buffer { + return buffer.setInt(pos, i) + } + + override fun setIntLE(pos: Int, i: Int): Buffer { + return buffer.setIntLE(pos, i) + } + + override fun setUnsignedInt(pos: Int, i: Long): Buffer { + return buffer.setUnsignedInt(pos, i) + } + + override fun setUnsignedIntLE(pos: Int, i: Long): Buffer { + return buffer.setUnsignedIntLE(pos, i) + } + + override fun setMedium(pos: Int, i: Int): Buffer { + return buffer.setMedium(pos, i) + } + + override fun setMediumLE(pos: Int, i: Int): Buffer { + return buffer.setMediumLE(pos, i) + } + + override fun setLong(pos: Int, l: Long): Buffer { + return buffer.setLong(pos, l) + } + + override fun setLongLE(pos: Int, l: Long): Buffer { + return buffer.setLongLE(pos, l) + } + + override fun setDouble(pos: Int, d: Double): Buffer { + return buffer.setDouble(pos, d) + } + + override fun setFloat(pos: Int, f: Float): Buffer { + return buffer.setFloat(pos, f) + } + + override fun setShort(pos: Int, s: Short): Buffer { + return buffer.setShort(pos, s) + } + + override fun setShortLE(pos: Int, s: Short): Buffer { + return buffer.setShortLE(pos, s) + } + + override fun setUnsignedShort(pos: Int, s: Int): Buffer { + return buffer.setUnsignedShort(pos, s) + } + + override fun setUnsignedShortLE(pos: Int, s: Int): Buffer { + return buffer.setUnsignedShortLE(pos, s) + } + + override fun setBuffer(pos: Int, b: Buffer?): Buffer { + return buffer.setBuffer(pos, b) + } + + override fun setBuffer(pos: Int, b: Buffer?, offset: Int, len: Int): Buffer { + return buffer.setBuffer(pos, b, offset, len) + } + + override fun setBytes(pos: Int, b: ByteBuffer?): Buffer { + return buffer.setBytes(pos, b) + } + + override fun setBytes(pos: Int, b: ByteArray?): Buffer { + return buffer.setBytes(pos, b) + } + + override fun setBytes(pos: Int, b: ByteArray?, offset: Int, len: Int): Buffer { + return buffer.setBytes(pos, b, offset, len) + } + + override fun setString(pos: Int, str: String?): Buffer { + return buffer.setString(pos, str) + } + + override fun setString(pos: Int, str: String?, enc: String?): Buffer { + return buffer.setString(pos, str, enc) + } + + override fun length(): Int { + return buffer.length() + } + + override fun slice(): Buffer { + return buffer.slice() + } + + override fun slice(start: Int, end: Int): Buffer { + return buffer.slice(start, end) + } + + @Deprecated("Deprecated in Java") + override fun getByteBuf(): ByteBuf { + return buffer.byteBuf + } +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt new file mode 100644 index 00000000000..fbf355e66a9 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/io/JsonResource.kt @@ -0,0 +1,15 @@ +package com.example.starter.io + +import io.vertx.core.json.JsonObject + +object JsonResource { + fun of(resource: String): JsonObject { + val classLoader = ClassLoader.getSystemClassLoader() + classLoader.getResourceAsStream(resource)?.use { input -> + val output = BufferOutputStream() + output.write(input.readAllBytes()) + return output.toJsonObject() + } + throw IllegalStateException("$resource not found") + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt new file mode 100644 index 00000000000..4b832526750 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Fortune.kt @@ -0,0 +1,14 @@ +package com.example.starter.models + +import com.dslplatform.json.CompiledJson +import com.dslplatform.json.JsonAttribute + +@CompiledJson +class Fortune( + @JsonAttribute(nullable = false) val id: Int, + @JsonAttribute(nullable = false) val message: String +) : Comparable { + override fun compareTo(other: Fortune): Int { + return message.compareTo(other.message) + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt new file mode 100644 index 00000000000..eb7fc6250a3 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/Message.kt @@ -0,0 +1,7 @@ +package com.example.starter.models + +import com.dslplatform.json.CompiledJson +import com.dslplatform.json.JsonAttribute + +@CompiledJson +class Message(@JsonAttribute(nullable = false) val message: String) diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt new file mode 100644 index 00000000000..5011a2bb2e0 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/models/World.kt @@ -0,0 +1,14 @@ +package com.example.starter.models + +import com.dslplatform.json.CompiledJson +import com.dslplatform.json.JsonAttribute + +@CompiledJson +class World( + @JsonAttribute(nullable = false) val id: Int, + @JsonAttribute(nullable = false) var randomNumber: Int +) : Comparable { + override fun compareTo(other: World): Int { + return id.compareTo(other.id) + } +} diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt new file mode 100644 index 00000000000..03d5a018575 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/FutureExtensions.kt @@ -0,0 +1,14 @@ +package com.example.starter.utils + +import io.vertx.core.CompositeFuture +import io.vertx.core.Future +import java.util.concurrent.TimeUnit +import kotlin.time.Duration + +inline fun CompositeFuture.array(): Array = Array(this.size()) { this.resultAt(it) } + +@Suppress("NOTHING_TO_INLINE") +inline fun > T.block(duration: Duration): R = this + .toCompletionStage() + .toCompletableFuture() + .get(duration.inWholeMilliseconds, TimeUnit.MILLISECONDS) \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt new file mode 100644 index 00000000000..87c965ca9b7 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/JsonExtensions.kt @@ -0,0 +1,19 @@ +package com.example.starter.utils + +import com.dslplatform.json.DslJson +import com.dslplatform.json.runtime.Settings +import com.example.starter.io.BufferOutputStream +import io.vertx.core.buffer.Buffer + +val DSL_JSON: DslJson = DslJson( + Settings.withRuntime() + .includeServiceLoader() + .useStringValuesCache(DslJson.SimpleStringCache()) +) + +@Suppress("NOTHING_TO_INLINE") +inline fun T.serialize(initialSizeHint: Int = 0): Buffer { + val output = BufferOutputStream(initialSizeHint) + DSL_JSON.serialize(this, output) + return output +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt new file mode 100644 index 00000000000..2e29e784914 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/PeriodicDateResolver.kt @@ -0,0 +1,16 @@ +package com.example.starter.utils + +import io.vertx.core.Vertx +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter + +object PeriodicDateResolver { + var current: String = next() + + fun init(vertx: Vertx) { + vertx.setPeriodic(1000L) { current = next() } + } + + @Suppress("NOTHING_TO_INLINE") + private inline fun next(): String = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()) +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt new file mode 100644 index 00000000000..c968777ff77 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/RowSetExtensions.kt @@ -0,0 +1,14 @@ +package com.example.starter.utils + +import io.vertx.sqlclient.Row +import io.vertx.sqlclient.RowSet + +// This extension relies on the assumption the mapper never returns null, as it is defined. Otherwise, +// we prevent the overhead from having to do another iteration over the loop for a `filterNotNull` check. +inline fun RowSet.mapToArray(mapper: (Row) -> U): Array { + val arr = arrayOfNulls(this.size()) + val iterator = this.iterator() + var index = 0 + while (iterator.hasNext()) arr[index++] = mapper(iterator.next()) + return arr as Array +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt new file mode 100644 index 00000000000..044d24b06ab --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/kotlin/com/example/starter/utils/ThrowableExtensions.kt @@ -0,0 +1,12 @@ +package com.example.starter.utils + +import io.netty.channel.unix.Errors +import io.netty.channel.unix.Errors.NativeIoException +import java.net.SocketException + +const val CONNECTION_RESET_MESSAGE = "Connection reset" + +fun Throwable.isConnectionReset(): Boolean { + return (this is NativeIoException && this.expectedErr() == Errors.ERRNO_ECONNRESET_NEGATIVE) + || (this is SocketException && this.message == CONNECTION_RESET_MESSAGE) +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json new file mode 100644 index 00000000000..a790bc93043 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/http-server-options.json @@ -0,0 +1,6 @@ +{ + "port": 8080, + "tcpFastOpen": true, + "receiveBufferSize": 262144, + "sendBufferSize": 262144 +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/log4j2.xml b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ebe0ad3cb74 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/log4j2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json new file mode 100644 index 00000000000..a145a0a51c5 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/src/main/resources/pg-connect-options.json @@ -0,0 +1,15 @@ +{ + "user": "benchmarkdbuser", + "password": "benchmarkdbpass", + "host": "tfb-database", + "port": 5432, + "database": "hello_world", + "cachePreparedStatements": true, + "preparedStatementCacheMaxSize": 512, + "preparedStatementCacheSqlLimit": 2048, + "tcpKeepAlive": true, + "tcpFastOpen": true, + "pipeliningLimit": 100000, + "receiveBufferSize": 262144, + "sendBufferSize": 262144 +} \ No newline at end of file diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile new file mode 100644 index 00000000000..0ef28c410d9 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson-postgresql.dockerfile @@ -0,0 +1,37 @@ +FROM gradle:8.9-jdk21 as gradle + +WORKDIR /vertx-web-kotlin-dsljson + +COPY src src +COPY build.gradle.kts build.gradle.kts +COPY gradle.properties gradle.properties +COPY settings.gradle.kts settings.gradle.kts + +RUN gradle shadowJar + +EXPOSE 8080 + +CMD java \ + -server \ + -Xms2G \ + -Xmx2G \ + -XX:+AlwaysPreTouch \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=512m \ + -XX:ReservedCodeCacheSize=512m \ + -XX:MaxInlineLevel=20 \ + -XX:+UseNUMA \ + -Dvertx.disableMetrics=true \ + -Dvertx.disableH2c=true \ + -Dvertx.disableWebsockets=true \ + -Dvertx.flashPolicyHandler=false \ + -Dvertx.threadChecks=false \ + -Dvertx.disableContextTimings=true \ + -Dvertx.disableTCCL=true \ + -Dvertx.disableHttpHeadersValidation=true \ + -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ + -Dio.netty.buffer.checkBounds=false \ + -Dio.netty.buffer.checkAccessible=false \ + -Dtfb.hasDB=true \ + -jar \ + build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar diff --git a/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile new file mode 100644 index 00000000000..a4a1c142cf5 --- /dev/null +++ b/frameworks/Kotlin/vertx-web-kotlin-dsljson/vertx-web-kotlin-dsljson.dockerfile @@ -0,0 +1,37 @@ +FROM gradle:8.9-jdk21 as gradle + +WORKDIR /vertx-web-kotlin-dsljson + +COPY src src +COPY build.gradle.kts build.gradle.kts +COPY gradle.properties gradle.properties +COPY settings.gradle.kts settings.gradle.kts + +RUN gradle shadowJar + +EXPOSE 8080 + +CMD java \ + -server \ + -Xms2G \ + -Xmx2G \ + -XX:+AlwaysPreTouch \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=512m \ + -XX:ReservedCodeCacheSize=512m \ + -XX:MaxInlineLevel=20 \ + -XX:+UseNUMA \ + -Dvertx.disableMetrics=true \ + -Dvertx.disableH2c=true \ + -Dvertx.disableWebsockets=true \ + -Dvertx.flashPolicyHandler=false \ + -Dvertx.threadChecks=false \ + -Dvertx.disableContextTimings=true \ + -Dvertx.disableTCCL=true \ + -Dvertx.disableHttpHeadersValidation=true \ + -Dlog4j2.contextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector \ + -Dio.netty.buffer.checkBounds=false \ + -Dio.netty.buffer.checkAccessible=false \ + -Dtfb.hasDB=false \ + -jar \ + build/libs/vertx-web-kotlin-dsljson-benchmark-1.0.0-SNAPSHOT-fat.jar From 64fd93c0849d6ecb869b7e427533d160cc5165f5 Mon Sep 17 00:00:00 2001 From: Yan Kun Date: Sat, 3 Aug 2024 00:00:17 +0800 Subject: [PATCH 62/62] [Scala/otavia] Add new framework otavia: Your shiny new IO & Actor programming model! (#9158) --- frameworks/Scala/otavia/.mill-version | 1 + frameworks/Scala/otavia/.scalafmt.conf | 16 ++ frameworks/Scala/otavia/README.MD | 13 ++ .../src/app/controller/DBController.scala | 106 ++++++++++ .../app/controller/FortuneController.scala | 41 ++++ .../benchmark/src/app/model/Fortune.scala | 7 + .../benchmark/src/app/model/Message.scala | 5 + .../benchmark/src/app/model/World.scala | 8 + .../otavia/benchmark/src/app/startup.scala | 70 +++++++ .../src/app/util/FortunesRender.scala | 64 ++++++ frameworks/Scala/otavia/benchmark_config.json | 53 +++++ frameworks/Scala/otavia/build.sc | 15 ++ frameworks/Scala/otavia/config.toml | 36 ++++ frameworks/Scala/otavia/millw | 194 ++++++++++++++++++ frameworks/Scala/otavia/millw.bat | 173 ++++++++++++++++ .../Scala/otavia/otavia-reserve.dockerfile | 15 ++ frameworks/Scala/otavia/otavia.dockerfile | 15 ++ 17 files changed, 832 insertions(+) create mode 100644 frameworks/Scala/otavia/.mill-version create mode 100644 frameworks/Scala/otavia/.scalafmt.conf create mode 100644 frameworks/Scala/otavia/README.MD create mode 100644 frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/model/Message.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/model/World.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/startup.scala create mode 100644 frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala create mode 100644 frameworks/Scala/otavia/benchmark_config.json create mode 100644 frameworks/Scala/otavia/build.sc create mode 100644 frameworks/Scala/otavia/config.toml create mode 100644 frameworks/Scala/otavia/millw create mode 100644 frameworks/Scala/otavia/millw.bat create mode 100644 frameworks/Scala/otavia/otavia-reserve.dockerfile create mode 100644 frameworks/Scala/otavia/otavia.dockerfile diff --git a/frameworks/Scala/otavia/.mill-version b/frameworks/Scala/otavia/.mill-version new file mode 100644 index 00000000000..772c67a500f --- /dev/null +++ b/frameworks/Scala/otavia/.mill-version @@ -0,0 +1 @@ +0.11.8 \ No newline at end of file diff --git a/frameworks/Scala/otavia/.scalafmt.conf b/frameworks/Scala/otavia/.scalafmt.conf new file mode 100644 index 00000000000..ff856188419 --- /dev/null +++ b/frameworks/Scala/otavia/.scalafmt.conf @@ -0,0 +1,16 @@ +version = "3.5.3" + +runner.dialect = scala3 +maxColumn = 120 +docstrings.blankFirstLine = no +docstrings.style = AsteriskSpace +docstrings.removeEmpty = true +docstrings.oneline = fold +docstrings.wrap = yes +docstrings.wrapMaxColumn = 120 +docstrings.forceBlankLineBefore = true +align.preset = more + +indent.main = 4 + +newlines.topLevelBodyIfMinStatements = [before,after] \ No newline at end of file diff --git a/frameworks/Scala/otavia/README.MD b/frameworks/Scala/otavia/README.MD new file mode 100644 index 00000000000..0ea11222811 --- /dev/null +++ b/frameworks/Scala/otavia/README.MD @@ -0,0 +1,13 @@ +## Introduction + +[GitHub - otavia-projects/otavia : Your shiny new IO & Actor programming model!](https://github.com/otavia-projects/otavia) + +`otavia` is an IO and Actor programming model power by Scala 3, it provides a toolkit to make writing high-performance +concurrent programs more easily. + +You can get a quick overview of the basic usage and core design of `otavia` in the following documentation: + +- [Quick Start](https://github.com/otavia-projects/otavia/blob/main/docs/_docs/quick_start.md) +- [Core Concepts and Design](https://github.com/otavia-projects/otavia/blob/main/docs/_docs/core_concept.md) + +More document can be found at [website](https://otavia.cc/home.html) \ No newline at end of file diff --git a/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala b/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala new file mode 100644 index 00000000000..6b54504aecc --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala @@ -0,0 +1,106 @@ +package app.controller + +import app.controller.DBController.* +import app.model.World +import cc.otavia.core.actor.{MessageOf, StateActor} +import cc.otavia.core.address.Address +import cc.otavia.core.message.{Ask, Reply} +import cc.otavia.core.stack.helper.{FutureState, FuturesState, StartState} +import cc.otavia.core.stack.{AskStack, StackState, StackYield} +import cc.otavia.http.server.{HttpRequest, HttpResponse} +import cc.otavia.sql.Connection +import cc.otavia.sql.Statement.{ModifyRows, PrepareQuery} + +import java.util.SplittableRandom + +class DBController extends StateActor[REQ] { + + private var connection: Address[MessageOf[Connection]] = _ + + private val random = new SplittableRandom() + + override protected def afterMount(): Unit = connection = autowire[Connection]() + + override protected def resumeAsk(stack: AskStack[REQ & Ask[? <: Reply]]): StackYield = + stack match + case stack: AskStack[SingleQueryRequest] if stack.ask.isInstanceOf[SingleQueryRequest] => + handleSingleQuery(stack) + case stack: AskStack[MultipleQueryRequest] if stack.ask.isInstanceOf[MultipleQueryRequest] => + handleMultipleQuery(stack) + case stack: AskStack[UpdateRequest] if stack.ask.isInstanceOf[UpdateRequest] => + handleUpdateQuery(stack) + + // Test 2: Single database query + private def handleSingleQuery(stack: AskStack[SingleQueryRequest]): StackYield = { + stack.state match + case _: StartState => + val state = FutureState[World]() + connection.ask(PrepareQuery.fetchOne[World](SELECT_WORLD, Tuple1(randomWorld())), state.future) + stack.suspend(state) + case state: FutureState[World] => + stack.`return`(state.future.getNow) + } + + // Test 3: Multiple database queries + private def handleMultipleQuery(stack: AskStack[MultipleQueryRequest]): StackYield = { + stack.state match + case _: StartState => + stack.suspend(selectWorlds(normalizeQueries(stack.ask.params))) + case state: FuturesState[World] => + val response = HttpResponse.builder.setContent(state.futures.map(_.getNow)).build() + stack.`return`(response) + } + + // Test 5: Database updates + private def handleUpdateQuery(stack: AskStack[UpdateRequest]): StackYield = { + stack.state match + case _: StartState => + stack.suspend(selectWorlds(normalizeQueries(stack.ask.params))) + case state: FuturesState[World] => + val worlds = state.futures.map(_.getNow) + stack.attach(worlds) + val newState = FutureState[ModifyRows]() + val newWorlds = worlds.sortBy(_.id).map(_.copy(randomNumber = randomWorld())) + connection.ask(PrepareQuery.update(UPDATE_WORLD, newWorlds), newState.future) + stack.suspend(newState) + case state: FutureState[ModifyRows] => + if (state.future.isFailed) state.future.causeUnsafe.printStackTrace() + val response = HttpResponse.builder.setContent(stack.attach[Seq[World]]).build() + stack.`return`(response) + } + + private def selectWorlds(queries: Int): StackState = { + val state = FuturesState[World](queries) + for (future <- state.futures) + connection.ask(PrepareQuery.fetchOne[World](SELECT_WORLD, Tuple1(randomWorld())), future) + state + } + + private def randomWorld(): Int = 1 + random.nextInt(10000) + + private def normalizeQueries(params: Map[String, String]): Int = { + params.get("queries") match + case Some(value) => + try { + val queries = value.toInt + if (queries < 1) 1 else if (queries > 500) 500 else queries + } catch { + case e: Throwable => 1 + } + case None => 1 + } + +} + +object DBController { + + type REQ = SingleQueryRequest | MultipleQueryRequest | UpdateRequest + + class SingleQueryRequest extends HttpRequest[Nothing, World] + class MultipleQueryRequest extends HttpRequest[Nothing, HttpResponse[Seq[World]]] + class UpdateRequest extends HttpRequest[Nothing, HttpResponse[Seq[World]]] + + private val SELECT_WORLD = "SELECT id, randomnumber from WORLD where id=$1" + private val UPDATE_WORLD = "update world set randomnumber=$2 where id=$1" + +} diff --git a/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala b/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala new file mode 100644 index 00000000000..05ff8c468ba --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala @@ -0,0 +1,41 @@ +package app.controller + +import app.controller.FortuneController.* +import app.model.Fortune +import cc.otavia.core.actor.{MessageOf, StateActor} +import cc.otavia.core.address.Address +import cc.otavia.core.stack.helper.{FutureState, StartState} +import cc.otavia.core.stack.{AskStack, StackState, StackYield} +import cc.otavia.http.server.{HttpRequest, HttpResponse} +import cc.otavia.sql.Statement.PrepareQuery +import cc.otavia.sql.{Connection, RowSet} + +class FortuneController extends StateActor[FortuneRequest] { + + private var connection: Address[MessageOf[Connection]] = _ + + override protected def afterMount(): Unit = connection = autowire[Connection]() + + // Test 4: Fortunes + override protected def resumeAsk(stack: AskStack[FortuneRequest]): StackYield = { + stack.state match + case _: StartState => + val state = FutureState[RowSet[Fortune]]() + connection.ask(PrepareQuery.fetchAll[Fortune](SELECT_FORTUNE), state.future) + stack.suspend(state) + case state: FutureState[RowSet[Fortune]] => + val fortunes = (state.future.getNow.rows :+ Fortune(0, "Additional fortune added at request time.")) + .sortBy(_.message) + val response = HttpResponse.builder.setContent(fortunes).build() + stack.`return`(response) + } + +} + +object FortuneController { + + class FortuneRequest extends HttpRequest[Nothing, HttpResponse[Seq[Fortune]]] + + private val SELECT_FORTUNE = "SELECT id, message from FORTUNE" + +} diff --git a/frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala b/frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala new file mode 100644 index 00000000000..edb58d3cdc9 --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala @@ -0,0 +1,7 @@ +package app.model + +import cc.otavia.json.JsonSerde +import cc.otavia.sql.{Row, RowDecoder} + +/** The model for the "fortune" database table. */ +case class Fortune(id: Int, message: String) extends Row derives RowDecoder, JsonSerde diff --git a/frameworks/Scala/otavia/benchmark/src/app/model/Message.scala b/frameworks/Scala/otavia/benchmark/src/app/model/Message.scala new file mode 100644 index 00000000000..a0d389090ae --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/model/Message.scala @@ -0,0 +1,5 @@ +package app.model + +import cc.otavia.json.JsonSerde + +case class Message(message: String) derives JsonSerde diff --git a/frameworks/Scala/otavia/benchmark/src/app/model/World.scala b/frameworks/Scala/otavia/benchmark/src/app/model/World.scala new file mode 100644 index 00000000000..a0e6f6056f8 --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/model/World.scala @@ -0,0 +1,8 @@ +package app.model + +import cc.otavia.json.JsonSerde +import cc.otavia.serde.annotation.rename +import cc.otavia.sql.{Row, RowDecoder} + +/** The model for the "world" database table. */ +case class World(id: Int, @rename("randomnumber") randomNumber: Int) extends Row derives RowDecoder, JsonSerde diff --git a/frameworks/Scala/otavia/benchmark/src/app/startup.scala b/frameworks/Scala/otavia/benchmark/src/app/startup.scala new file mode 100644 index 00000000000..32eb0c2e539 --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/startup.scala @@ -0,0 +1,70 @@ +package app + +import app.controller.DBController.* +import app.controller.FortuneController.* +import app.controller.{DBController, FortuneController} +import app.model.* +import app.util.FortunesRender +import cc.otavia.core.actor.ChannelsActor.{Bind, ChannelEstablished} +import cc.otavia.core.actor.MainActor +import cc.otavia.core.slf4a.LoggerFactory +import cc.otavia.core.stack.helper.{FutureState, StartState} +import cc.otavia.core.stack.{NoticeStack, StackYield} +import cc.otavia.core.system.ActorSystem +import cc.otavia.http.HttpMethod.* +import cc.otavia.http.MediaType +import cc.otavia.http.MediaType.* +import cc.otavia.http.server.* +import cc.otavia.http.server.Router.* +import cc.otavia.json.JsonSerde +import cc.otavia.serde.helper.BytesSerde +import cc.otavia.sql.Connection + +import java.io.File +import java.nio.charset.StandardCharsets.UTF_8 +import java.nio.file.Path + +private class ServerMain(val port: Int = 8080) extends MainActor(Array.empty) { + + override def main0(stack: NoticeStack[MainActor.Args]): StackYield = stack.state match + case _: StartState => + val worldResponseSerde = HttpResponseSerde.json(summon[JsonSerde[World]]) + val worldsResponseSerde = HttpResponseSerde.json(JsonSerde.derived[Seq[World]]) + val fortunesResponseSerde = HttpResponseSerde(new FortunesRender(), MediaType.TEXT_HTML_UTF8) + + val dbController = autowire[DBController]() + val fortuneController = autowire[FortuneController]() + + val routers = Seq( + // Test 6: plaintext + constant[Array[Byte]](GET, "/plaintext", "Hello, World!".getBytes(UTF_8), BytesSerde, TEXT_PLAIN_UTF8), + // Test 1: JSON serialization + constant[Message](GET, "/json", Message("Hello, World!"), summon[JsonSerde[Message]], APP_JSON), + // Test 2: Single database query. + get("/db", dbController, () => new SingleQueryRequest(), worldResponseSerde), + // Test 3: Multiple database queries + get("/queries", dbController, () => new MultipleQueryRequest(), worldsResponseSerde), + // Test 5: Database updates + get("/updates", dbController, () => new UpdateRequest(), worldsResponseSerde), + // Test 4: Fortunes + get("/fortunes", fortuneController, () => new FortuneRequest(), fortunesResponseSerde) + ) + val server = system.buildActor(() => new HttpServer(system.actorWorkerSize, routers)) + val state = FutureState[ChannelEstablished]() + server.ask(Bind(port), state.future) + stack.suspend(state) + case state: FutureState[ChannelEstablished] => + if (state.future.isFailed) state.future.causeUnsafe.printStackTrace() + logger.info(s"http server bind port $port success") + stack.`return`() + +} + +@main def startup(url: String, user: String, password: String, poolSize: Int): Unit = + val system = ActorSystem() + val logger = LoggerFactory.getLogger("startup", system) + logger.info("starting http server") + system.buildActor(() => new Connection(url, user, password), global = true, num = poolSize) + system.buildActor(() => new DBController(), global = true, num = system.actorWorkerSize) + system.buildActor(() => new FortuneController(), global = true, num = system.actorWorkerSize) + system.buildActor(() => new ServerMain()) diff --git a/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala b/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala new file mode 100644 index 00000000000..0c0694ee836 --- /dev/null +++ b/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala @@ -0,0 +1,64 @@ +package app.util + +import app.model.Fortune +import cc.otavia.buffer.{Buffer, BufferUtils} +import cc.otavia.serde.Serde + +import java.nio.charset.StandardCharsets +import scala.annotation.switch + +class FortunesRender extends Serde[Seq[Fortune]] { + + private val text1 = + "Fortunes" + .getBytes(StandardCharsets.UTF_8) + + private val text2 = "".getBytes(StandardCharsets.UTF_8) + + private val text5 = "
idmessage
".getBytes(StandardCharsets.UTF_8) + + private val text3 = "".getBytes(StandardCharsets.UTF_8) + + private val text4 = "
".getBytes(StandardCharsets.UTF_8) + + private val lt = "<".getBytes() + private val gt = ">".getBytes() + private val quot = """.getBytes() + private val squot = "'".getBytes() + private val amp = "&".getBytes() + + override def serialize(fortunes: Seq[Fortune], out: Buffer): Unit = { + out.writeBytes(text1) + for (fortune <- fortunes) { + out.writeBytes(text2) + BufferUtils.writeIntAsString(out, fortune.id) + out.writeBytes(text3) + writeEscapeMessage(out, fortune.message) + out.writeBytes(text4) + } + out.writeBytes(text5) + } + + override def deserialize(in: Buffer): Seq[Fortune] = throw new UnsupportedOperationException() + + private def writeEscapeMessage(buffer: Buffer, message: String): Unit = { + var i = 0 + while (i < message.length) { + val ch = message.charAt(i) + writeChar(buffer, ch) + i += 1 + } + } + + private def writeChar(buffer: Buffer, ch: Char): Unit = (ch: @switch) match + case '<' => buffer.writeBytes(lt) + case '>' => buffer.writeBytes(gt) + case '"' => buffer.writeBytes(quot) + case '\'' => buffer.writeBytes(squot) + case '&' => buffer.writeBytes(amp) + case _ => + if (ch < 0x80) buffer.writeByte(ch.toByte) + else if (ch < 0x800) buffer.writeShortLE((ch >> 6 | (ch << 8 & 0x3f00) | 0x80c0).toShort) + else buffer.writeMediumLE(ch >> 12 | (ch << 2 & 0x3f00) | (ch << 16 & 0x3f0000) | 0x8080e0) + +} diff --git a/frameworks/Scala/otavia/benchmark_config.json b/frameworks/Scala/otavia/benchmark_config.json new file mode 100644 index 00000000000..ae712574778 --- /dev/null +++ b/frameworks/Scala/otavia/benchmark_config.json @@ -0,0 +1,53 @@ +{ + "framework": "otavia", + "tests": [ + { + "default": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/updates?queries=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "otavia", + "language": "Scala", + "flavor": "None", + "orm": "Micro", + "platform": "Otavia", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "otavia", + "notes": "", + "versus": "Otavia" + }, + "reserve": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?queries=", + "fortune_url": "/fortunes", + "update_url": "/updates?queries=", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "otavia", + "language": "Scala", + "flavor": "None", + "orm": "Micro", + "platform": "Otavia", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "otavia", + "notes": "", + "versus": "Otavia" + } + } + ] +} diff --git a/frameworks/Scala/otavia/build.sc b/frameworks/Scala/otavia/build.sc new file mode 100644 index 00000000000..2b7877b7891 --- /dev/null +++ b/frameworks/Scala/otavia/build.sc @@ -0,0 +1,15 @@ +import mill._ +import mill.scalalib._ + +def otaviaVersion = "0.4.0" + +object benchmark extends ScalaModule { + + override def scalaVersion = "3.3.1" + + override def ivyDeps = Agg( + ivy"cc.otavia::otavia-codec-http:$otaviaVersion", + ivy"cc.otavia::otavia-postgres-driver:$otaviaVersion" + ) + +} diff --git a/frameworks/Scala/otavia/config.toml b/frameworks/Scala/otavia/config.toml new file mode 100644 index 00000000000..96613dfd2fd --- /dev/null +++ b/frameworks/Scala/otavia/config.toml @@ -0,0 +1,36 @@ +[framework] +name = "otavia" + +[main] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/queries?queries=" +urls.update = "/updates?queries=" +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Micro" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Micro" +platform = "Otavia" +webserver = "None" +versus = "Otavia" + +[reserve] +urls.plaintext = "/plaintext" +urls.json = "/json" +urls.db = "/db" +urls.query = "/queries?queries=" +urls.update = "/updates?queries=" +urls.fortune = "/fortunes" +approach = "Realistic" +classification = "Micro" +database = "Postgres" +database_os = "Linux" +os = "Linux" +orm = "Micro" +platform = "Otavia" +webserver = "None" +versus = "Otavia" diff --git a/frameworks/Scala/otavia/millw b/frameworks/Scala/otavia/millw new file mode 100644 index 00000000000..73bb4d0e4a0 --- /dev/null +++ b/frameworks/Scala/otavia/millw @@ -0,0 +1,194 @@ +#!/usr/bin/env sh + +# This is a wrapper script, that automatically download mill from GitHub release pages +# You can give the required mill version with --mill-version parameter +# If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +# +# Project page: https://github.com/lefou/millw +# Script Version: 0.4.6 +# +# If you want to improve this script, please also contribute your changes back! +# +# Licensed under the Apache License, Version 2.0 + +set -e + +if [ -z "${DEFAULT_MILL_VERSION}" ] ; then + DEFAULT_MILL_VERSION="0.10.10" +fi + + +if [ -z "${GITHUB_RELEASE_CDN}" ] ; then + GITHUB_RELEASE_CDN="" +fi + + +MILL_REPO_URL="https://github.com/com-lihaoyi/mill" + +if [ -z "${CURL_CMD}" ] ; then + CURL_CMD=curl +fi + +# Explicit commandline argument takes precedence over all other methods +if [ "$1" = "--mill-version" ] ; then + shift + if [ "x$1" != "x" ] ; then + MILL_VERSION="$1" + shift + else + echo "You specified --mill-version without a version." 1>&2 + echo "Please provide a version that matches one provided on" 1>&2 + echo "${MILL_REPO_URL}/releases" 1>&2 + false + fi +fi + +# Please note, that if a MILL_VERSION is already set in the environment, +# We reuse it's value and skip searching for a value. + +# If not already set, read .mill-version file +if [ -z "${MILL_VERSION}" ] ; then + if [ -f ".mill-version" ] ; then + MILL_VERSION="$(head -n 1 .mill-version 2> /dev/null)" + elif [ -f ".config/mill-version" ] ; then + MILL_VERSION="$(head -n 1 .config/mill-version 2> /dev/null)" + fi +fi + +if [ -n "${XDG_CACHE_HOME}" ] ; then + MILL_DOWNLOAD_PATH="${XDG_CACHE_HOME}/mill/download" +else + MILL_DOWNLOAD_PATH="${HOME}/.cache/mill/download" +fi + +# If not already set, try to fetch newest from Github +if [ -z "${MILL_VERSION}" ] ; then + # TODO: try to load latest version from release page + echo "No mill version specified." 1>&2 + echo "You should provide a version via '.mill-version' file or --mill-version option." 1>&2 + + mkdir -p "${MILL_DOWNLOAD_PATH}" + LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" 2>/dev/null || ( + # we might be on OSX or BSD which don't have -d option for touch + # but probably a -A [-][[hh]mm]SS + touch "${MILL_DOWNLOAD_PATH}/.expire_latest"; touch -A -010000 "${MILL_DOWNLOAD_PATH}/.expire_latest" + ) || ( + # in case we still failed, we retry the first touch command with the intention + # to show the (previously suppressed) error message + LANG=C touch -d '1 hour ago' "${MILL_DOWNLOAD_PATH}/.expire_latest" + ) + + # POSIX shell variant of bash's -nt operator, see https://unix.stackexchange.com/a/449744/6993 + # if [ "${MILL_DOWNLOAD_PATH}/.latest" -nt "${MILL_DOWNLOAD_PATH}/.expire_latest" ] ; then + if [ -n "$(find -L "${MILL_DOWNLOAD_PATH}/.latest" -prune -newer "${MILL_DOWNLOAD_PATH}/.expire_latest")" ]; then + # we know a current latest version + MILL_VERSION=$(head -n 1 "${MILL_DOWNLOAD_PATH}"/.latest 2> /dev/null) + fi + + if [ -z "${MILL_VERSION}" ] ; then + # we don't know a current latest version + echo "Retrieving latest mill version ..." 1>&2 + LANG=C ${CURL_CMD} -s -i -f -I ${MILL_REPO_URL}/releases/latest 2> /dev/null | grep --ignore-case Location: | sed s'/^.*tag\///' | tr -d '\r\n' > "${MILL_DOWNLOAD_PATH}/.latest" + MILL_VERSION=$(head -n 1 "${MILL_DOWNLOAD_PATH}"/.latest 2> /dev/null) + fi + + if [ -z "${MILL_VERSION}" ] ; then + # Last resort + MILL_VERSION="${DEFAULT_MILL_VERSION}" + echo "Falling back to hardcoded mill version ${MILL_VERSION}" 1>&2 + else + echo "Using mill version ${MILL_VERSION}" 1>&2 + fi +fi + +MILL="${MILL_DOWNLOAD_PATH}/${MILL_VERSION}" + +try_to_use_system_mill() { + MILL_IN_PATH="$(command -v mill || true)" + + if [ -z "${MILL_IN_PATH}" ]; then + return + fi + + UNIVERSAL_SCRIPT_MAGIC="@ 2>/dev/null # 2>nul & echo off & goto BOF" + + if ! head -c 128 "${MILL_IN_PATH}" | grep -qF "${UNIVERSAL_SCRIPT_MAGIC}"; then + if [ -n "${MILLW_VERBOSE}" ]; then + echo "Could not determine mill version of ${MILL_IN_PATH}, as it does not start with the universal script magic2" 1>&2 + fi + return + fi + + # Roughly the size of the universal script. + MILL_VERSION_SEARCH_RANGE="2403" + MILL_IN_PATH_VERSION=$(head -c "${MILL_VERSION_SEARCH_RANGE}" "${MILL_IN_PATH}" |\ + sed -n 's/^.*-DMILL_VERSION=\([^\s]*\) .*$/\1/p' |\ + head -n 1) + + if [ -z "${MILL_IN_PATH_VERSION}" ]; then + echo "Could not determine mill version, even though ${MILL_IN_PATH} has the universal script magic" 1>&2 + return + fi + + if [ "${MILL_IN_PATH_VERSION}" = "${MILL_VERSION}" ]; then + MILL="${MILL_IN_PATH}" + fi +} +try_to_use_system_mill + +# If not already downloaded, download it +if [ ! -s "${MILL}" ] ; then + + # support old non-XDG download dir + MILL_OLD_DOWNLOAD_PATH="${HOME}/.mill/download" + OLD_MILL="${MILL_OLD_DOWNLOAD_PATH}/${MILL_VERSION}" + if [ -x "${OLD_MILL}" ] ; then + MILL="${OLD_MILL}" + else + VERSION_PREFIX="$(echo $MILL_VERSION | cut -b -4)" + case $VERSION_PREFIX in + 0.0. | 0.1. | 0.2. | 0.3. | 0.4. ) + DOWNLOAD_SUFFIX="" + ;; + *) + DOWNLOAD_SUFFIX="-assembly" + ;; + esac + unset VERSION_PREFIX + + DOWNLOAD_FILE=$(mktemp mill.XXXXXX) + MILL_VERSION_TAG=$(echo $MILL_VERSION | sed -E 's/([^-]+)(-M[0-9]+)?(-.*)?/\1\2/') + DOWNLOAD_URL="${GITHUB_RELEASE_CDN}${MILL_REPO_URL}/releases/download/${MILL_VERSION_TAG}/${MILL_VERSION}${DOWNLOAD_SUFFIX}" + # TODO: handle command not found + echo "Downloading mill ${MILL_VERSION} from ${DOWNLOAD_URL} ..." 1>&2 + ${CURL_CMD} -f -L -o "${DOWNLOAD_FILE}" ${DOWNLOAD_URL} + chmod +x "${DOWNLOAD_FILE}" + mkdir -p "${MILL_DOWNLOAD_PATH}" + mv "${DOWNLOAD_FILE}" "${MILL}" + + unset DOWNLOAD_FILE + unset DOWNLOAD_SUFFIX + fi +fi + +if [ -z "$MILL_MAIN_CLI" ] ; then + MILL_MAIN_CLI="${0}" +fi + +MILL_FIRST_ARG="" +if [ "$1" = "--bsp" ] || [ "$1" = "-i" ] || [ "$1" = "--interactive" ] || [ "$1" = "--no-server" ] || [ "$1" = "--repl" ] || [ "$1" = "--help" ] ; then + # Need to preserve the first position of those listed options + MILL_FIRST_ARG=$1 + shift +fi + +unset MILL_DOWNLOAD_PATH +unset MILL_OLD_DOWNLOAD_PATH +unset OLD_MILL +unset MILL_VERSION +unset MILL_VERSION_TAG +unset MILL_REPO_URL + +# We don't quote MILL_FIRST_ARG on purpose, so we can expand the empty value without quotes +# shellcheck disable=SC2086 +exec "${MILL}" $MILL_FIRST_ARG -D "mill.main.cli=${MILL_MAIN_CLI}" "$@" diff --git a/frameworks/Scala/otavia/millw.bat b/frameworks/Scala/otavia/millw.bat new file mode 100644 index 00000000000..6359e35e500 --- /dev/null +++ b/frameworks/Scala/otavia/millw.bat @@ -0,0 +1,173 @@ +@echo off + +rem This is a wrapper script, that automatically download mill from GitHub release pages +rem You can give the required mill version with --mill-version parameter +rem If no version is given, it falls back to the value of DEFAULT_MILL_VERSION +rem +rem Project page: https://github.com/lefou/millw +rem Script Version: 0.4.6 +rem +rem If you want to improve this script, please also contribute your changes back! +rem +rem Licensed under the Apache License, Version 2.0 + +rem setlocal seems to be unavailable on Windows 95/98/ME +rem but I don't think we need to support them in 2019 +setlocal enabledelayedexpansion + +if [!DEFAULT_MILL_VERSION!]==[] ( + set "DEFAULT_MILL_VERSION=0.10.10" +) + +if [!GITHUB_RELEASE_CDN!]==[] ( + set "GITHUB_RELEASE_CDN=" +) + +set "MILL_REPO_URL=https://github.com/com-lihaoyi/mill" + +rem %~1% removes surrounding quotes +if [%~1%]==[--mill-version] ( + if not [%~2%]==[] ( + set MILL_VERSION=%~2% + rem shift command doesn't work within parentheses + set "STRIP_VERSION_PARAMS=true" + ) else ( + echo You specified --mill-version without a version. 1>&2 + echo Please provide a version that matches one provided on 1>&2 + echo %MILL_REPO_URL%/releases 1>&2 + exit /b 1 + ) +) + +if not defined STRIP_VERSION_PARAMS GOTO AfterStripVersionParams +rem strip the: --mill-version {version} +shift +shift +:AfterStripVersionParams + +if [!MILL_VERSION!]==[] ( + if exist .mill-version ( + set /p MILL_VERSION=<.mill-version + ) else ( + if exist .config\mill-version ( + set /p MILL_VERSION=<.config\mill-version + ) + ) +) + +if [!MILL_VERSION!]==[] ( + set MILL_VERSION=%DEFAULT_MILL_VERSION% +) + +set MILL_DOWNLOAD_PATH=%USERPROFILE%\.mill\download + +rem without bat file extension, cmd doesn't seem to be able to run it +set MILL=%MILL_DOWNLOAD_PATH%\!MILL_VERSION!.bat + +if not exist "%MILL%" ( + set VERSION_PREFIX=%MILL_VERSION:~0,4% + set DOWNLOAD_SUFFIX=-assembly + if [!VERSION_PREFIX!]==[0.0.] set DOWNLOAD_SUFFIX= + if [!VERSION_PREFIX!]==[0.1.] set DOWNLOAD_SUFFIX= + if [!VERSION_PREFIX!]==[0.2.] set DOWNLOAD_SUFFIX= + if [!VERSION_PREFIX!]==[0.3.] set DOWNLOAD_SUFFIX= + if [!VERSION_PREFIX!]==[0.4.] set DOWNLOAD_SUFFIX= + set VERSION_PREFIX= + + for /F "delims=- tokens=1" %%A in ("!MILL_VERSION!") do set MILL_VERSION_BASE=%%A + for /F "delims=- tokens=2" %%A in ("!MILL_VERSION!") do set MILL_VERSION_MILESTONE=%%A + set VERSION_MILESTONE_START=!MILL_VERSION_MILESTONE:~0,1! + if [!VERSION_MILESTONE_START!]==[M] ( + set MILL_VERSION_TAG="!MILL_VERSION_BASE!-!MILL_VERSION_MILESTONE!" + ) else ( + set MILL_VERSION_TAG=!MILL_VERSION_BASE! + ) + + rem there seems to be no way to generate a unique temporary file path (on native Windows) + set DOWNLOAD_FILE=%MILL%.tmp + + set DOWNLOAD_URL=!GITHUB_RELEASE_CDN!%MILL_REPO_URL%/releases/download/!MILL_VERSION_TAG!/!MILL_VERSION!!DOWNLOAD_SUFFIX! + + echo Downloading mill %MILL_VERSION% from !DOWNLOAD_URL! ... 1>&2 + + if not exist "%MILL_DOWNLOAD_PATH%" mkdir "%MILL_DOWNLOAD_PATH%" + rem curl is bundled with recent Windows 10 + rem but I don't think we can expect all the users to have it in 2019 + where /Q curl + if %ERRORLEVEL% EQU 0 ( + curl -f -L "!DOWNLOAD_URL!" -o "!DOWNLOAD_FILE!" + ) else ( + rem bitsadmin seems to be available on Windows 7 + rem without /dynamic, github returns 403 + rem bitsadmin is sometimes needlessly slow but it looks better with /priority foreground + bitsadmin /transfer millDownloadJob /dynamic /priority foreground "!DOWNLOAD_URL!" "!DOWNLOAD_FILE!" + ) + if not exist "!DOWNLOAD_FILE!" ( + echo Could not download mill %MILL_VERSION% 1>&2 + exit /b 1 + ) + + move /y "!DOWNLOAD_FILE!" "%MILL%" + + set DOWNLOAD_FILE= + set DOWNLOAD_SUFFIX= +) + +set MILL_DOWNLOAD_PATH= +set MILL_VERSION= +set MILL_REPO_URL= + +if [!MILL_MAIN_CLI!]==[] ( + set "MILL_MAIN_CLI=%0" +) + +rem Need to preserve the first position of those listed options +set MILL_FIRST_ARG= +if [%~1%]==[--bsp] ( + set MILL_FIRST_ARG=%1% +) else ( + if [%~1%]==[-i] ( + set MILL_FIRST_ARG=%1% + ) else ( + if [%~1%]==[--interactive] ( + set MILL_FIRST_ARG=%1% + ) else ( + if [%~1%]==[--no-server] ( + set MILL_FIRST_ARG=%1% + ) else ( + if [%~1%]==[--repl] ( + set MILL_FIRST_ARG=%1% + ) else ( + if [%~1%]==[--help] ( + set MILL_FIRST_ARG=%1% + ) + ) + ) + ) + ) +) + +set "MILL_PARAMS=%*%" + +if not [!MILL_FIRST_ARG!]==[] ( + if defined STRIP_VERSION_PARAMS ( + for /f "tokens=1-3*" %%a in ("%*") do ( + set "MILL_PARAMS=%%d" + ) + ) else ( + for /f "tokens=1*" %%a in ("%*") do ( + set "MILL_PARAMS=%%b" + ) + ) +) else ( + if defined STRIP_VERSION_PARAMS ( + for /f "tokens=1-2*" %%a in ("%*") do ( + rem strip %%a - It's the "--mill-version" option. + rem strip %%b - it's the version number that comes after the option. + rem keep %%c - It's the remaining options. + set "MILL_PARAMS=%%c" + ) + ) +) + +"%MILL%" %MILL_FIRST_ARG% -D "mill.main.cli=%MILL_MAIN_CLI%" %MILL_PARAMS% diff --git a/frameworks/Scala/otavia/otavia-reserve.dockerfile b/frameworks/Scala/otavia/otavia-reserve.dockerfile new file mode 100644 index 00000000000..5768000706e --- /dev/null +++ b/frameworks/Scala/otavia/otavia-reserve.dockerfile @@ -0,0 +1,15 @@ +FROM nightscape/scala-mill:eclipse-temurin-17.0.8.1_1-jdk-focal_0.11.6_3.3.0 +WORKDIR /otavia +COPY benchmark benchmark +COPY build.sc build.sc +ENV COURSIER_REPOSITORIES=ivy2Local|central +RUN mill benchmark.assembly + +EXPOSE 8080 + +CMD java -server \ + -Dcc.otavia.actor.worker.size=18 -Dcc.otavia.nio.worker.size=36 \ + -jar \ + out/benchmark/assembly.dest/out.jar \ + jdbc:postgresql://tfb-database:5432/hello_world \ + benchmarkdbuser benchmarkdbpass 54 diff --git a/frameworks/Scala/otavia/otavia.dockerfile b/frameworks/Scala/otavia/otavia.dockerfile new file mode 100644 index 00000000000..c1c944d60aa --- /dev/null +++ b/frameworks/Scala/otavia/otavia.dockerfile @@ -0,0 +1,15 @@ +FROM nightscape/scala-mill:eclipse-temurin-17.0.8.1_1-jdk-focal_0.11.6_3.3.0 +WORKDIR /otavia +COPY benchmark benchmark +COPY build.sc build.sc +ENV COURSIER_REPOSITORIES=ivy2Local|central +RUN mill benchmark.assembly + +EXPOSE 8080 + +CMD java -server \ + -Dcc.otavia.actor.worker.size=24 -Dcc.otavia.nio.worker.size=48 \ + -jar \ + out/benchmark/assembly.dest/out.jar \ + jdbc:postgresql://tfb-database:5432/hello_world \ + benchmarkdbuser benchmarkdbpass 72