From 02764ebed3b95d09611908ee3b50c7e6c5881462 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 08:33:58 -0700 Subject: [PATCH 01/40] Bump webob from 1.7.2 to 1.8.8 in /frameworks/Python/morepath (#9215) Bumps [webob](https://github.com/Pylons/webob) from 1.7.2 to 1.8.8. - [Changelog](https://github.com/Pylons/webob/blob/main/CHANGES.txt) - [Commits](https://github.com/Pylons/webob/compare/1.7.2...1.8.8) --- updated-dependencies: - dependency-name: webob dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- frameworks/Python/morepath/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Python/morepath/requirements.txt b/frameworks/Python/morepath/requirements.txt index b1ff4b72a3a..8f58488b64e 100644 --- a/frameworks/Python/morepath/requirements.txt +++ b/frameworks/Python/morepath/requirements.txt @@ -12,6 +12,6 @@ pony==0.7.1 psycopg2==2.7.5 reg==0.11 repoze.lru==0.6 -WebOb==1.7.2 +WebOb==1.8.8 -e . From 9c9b8678aabb9aa783f8379c8cd0e318771cd0b5 Mon Sep 17 00:00:00 2001 From: LLT21 <43903768+LLT21@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:06:15 +0200 Subject: [PATCH 02/40] Appmpowerv8.0.5: using native AOT dll instead of exe (#9214) * New Npgsql security update * Middleware alternative * NativeAOT calls * hellloWorld -> helloWorld * Reduce external calls * JsonMiddleware * JsonMessage built in NativeAOT * mac dylibs * Size and content separate * Small corrections * JsonMessage * JsonMessage struct * Rename nativeAOT -> appMpowerAot * Working single query, but slow * Odbc test * dockerfile changes * Try to get correct capitalization * 2nd part trial for correct capitalization * Dbms and DbProvider parameterization * linux-x64 * NativeMethods * Kestrel header * Header http * Using marshalling and out parameter * Header changes * FreeUnmanagedPointer * Correction single query * JsonMessage pointer handling * Native last methods for JsonMessage and hello world * Sync db read * Create new json message * Rename appMpowerAot -> appMpower.Orm * Fortunes * Synchronous fortunes read * Server settings * Empty line * More correct special characters length * Remove ADO and InternalConnection * Synchronous only * Cleanup * Name changes * Multiple queries * Cleanup * Alternative native methods * MultipleUpdates * odbcCommand dictionary * keyed commands * Refactoring * Remove comments * First MySQL trial * MySQL odbc * zip file mariadb connector * Better download ? * dockerfile cleanup * charset * Cached queries * Improved caching * Improved caching * Removal unnecessary packages * Cleanup project * appMpower cleanup * appMpower.Orm cleanup * Too much cleanup --------- Co-authored-by: LLT21 <> --- .../appmpower/appmpower-ado-pg.dockerfile | 17 - .../appmpower/appmpower-odbc-my.dockerfile | 51 ++ .../appmpower/appmpower-odbc-pg.dockerfile | 8 +- .../CSharp/appmpower/appmpower.dockerfile | 6 + .../CSharp/appmpower/benchmark_config.json | 8 +- frameworks/CSharp/appmpower/config.toml | 4 +- frameworks/CSharp/appmpower/odbcinst.ini | 10 + .../appmpower/src/CachedWorldSerializer.cs | 15 - .../CSharp/appmpower/src/Data/DbConnection.cs | 200 ------- .../appmpower/src/Data/DbConnections.cs | 67 --- .../appmpower/src/Data/DbProviderFactory.cs | 17 - .../appmpower/src/Data/InternalConnection.cs | 16 - .../CSharp/appmpower/src/HttpApplication.cs | 117 ---- .../CSharp/appmpower/src/JsonMessage.cs | 7 - .../CSharp/appmpower/src/Kestrel/Json.cs | 58 -- .../CSharp/appmpower/src/Kestrel/PlainText.cs | 38 -- .../appmpower/src/Kestrel/ServiceProvider.cs | 25 - .../CSharp/appmpower/src/Memory/CacheEntry.cs | 257 --------- .../appmpower/src/Memory/CacheEntryHelper.cs | 32 -- .../appmpower/src/Memory/CacheEntryState.cs | 62 --- .../appmpower/src/Memory/CacheEntryTokens.cs | 140 ----- .../appmpower/src/Memory/MemoryCache.cs | 520 ------------------ .../src/Memory/MemoryCacheOptions.cs | 67 --- .../CSharp/appmpower/src/Microsoft/CachKey.cs | 24 - .../src/Microsoft/StringBuilderCache.cs | 59 -- frameworks/CSharp/appmpower/src/Program.cs | 42 -- frameworks/CSharp/appmpower/src/RawDb.cs | 331 ----------- .../appmpower/src/appMpower.Orm/Constants.cs | 10 + .../src/{ => appMpower.Orm}/Data/DbCommand.cs | 105 ++-- .../src/appMpower.Orm/Data/DbConnection.cs | 153 ++++++ .../src/appMpower.Orm/Data/DbConnections.cs | 61 ++ .../src/appMpower.Orm/Data/DbProvider.cs | 8 + .../appMpower.Orm/Data/DbProviderFactory.cs | 21 + .../appmpower/src/appMpower.Orm/Data/Dbms.cs | 9 + .../src/appMpower.Orm/DotnetMethods.cs | 66 +++ .../src/{ => appMpower.Orm}/FortunesView.cs | 21 +- .../Microsoft/BatchUpdateString.cs | 56 +- .../Microsoft/ConcurrentRandom.cs | 2 - .../Microsoft/StringBuilderCache.cs | 54 ++ .../src/appMpower.Orm/NativeMethods.cs | 144 +++++ .../Objects}/CachedWorld.cs | 2 +- .../{ => appMpower.Orm/Objects}/Fortune.cs | 4 +- .../src/{ => appMpower.Orm/Objects}/World.cs | 2 +- .../appmpower/src/appMpower.Orm/RawDb.cs | 257 +++++++++ .../Serializers/IJsonSerializer.cs | 9 + .../Serializers}/WorldSerializer.cs | 6 +- .../Serializers/WorldsSerizalizer.cs | 24 + .../appMpower.Orm.csproj} | 97 ++-- .../appmpower/src/appMpower/JsonMessage.cs | 7 + .../appMpower/Middleware/CachingMiddelware.cs | 120 ++++ .../Middleware/FortunesMiddleware.cs | 58 ++ .../appMpower/Middleware/JsonMiddleware.cs | 64 +++ .../Middleware/MultipleQueriesMiddleware.cs | 62 +++ .../Middleware/MultipleUpdatesMiddleware.cs | 62 +++ .../Middleware/PlaintextMiddleware.cs | 50 ++ .../Middleware/SingleQueryMiddleware.cs | 57 ++ .../appmpower/src/appMpower/NativeMethods.cs | 62 +++ .../CSharp/appmpower/src/appMpower/Program.cs | 44 ++ .../Serializers}/IJsonSerializer.cs | 2 +- .../Serializers}/JsonMessageSerializer.cs | 6 +- .../CSharp/appmpower/src/appMpower/Startup.cs | 56 ++ .../appmpower/src/appMpower/appMpower.csproj | 35 ++ .../appmpower/src/appMpower/appsettings.json | 9 + .../src/{ => appMpower}/nuget.config | 0 frameworks/CSharp/appmpower/src/src.sln | 28 + 65 files changed, 1728 insertions(+), 2303 deletions(-) delete mode 100644 frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile create mode 100644 frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile delete mode 100644 frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs delete mode 100644 frameworks/CSharp/appmpower/src/Data/DbConnection.cs delete mode 100644 frameworks/CSharp/appmpower/src/Data/DbConnections.cs delete mode 100644 frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs delete mode 100644 frameworks/CSharp/appmpower/src/Data/InternalConnection.cs delete mode 100644 frameworks/CSharp/appmpower/src/HttpApplication.cs delete mode 100644 frameworks/CSharp/appmpower/src/JsonMessage.cs delete mode 100644 frameworks/CSharp/appmpower/src/Kestrel/Json.cs delete mode 100644 frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs delete mode 100644 frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs delete mode 100644 frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs delete mode 100644 frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs delete mode 100644 frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs delete mode 100644 frameworks/CSharp/appmpower/src/Program.cs delete mode 100644 frameworks/CSharp/appmpower/src/RawDb.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm}/Data/DbCommand.cs (52%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm}/FortunesView.cs (54%) rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm}/Microsoft/BatchUpdateString.cs (54%) rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm}/Microsoft/ConcurrentRandom.cs (95%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm/Objects}/CachedWorld.cs (88%) rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm/Objects}/Fortune.cs (93%) rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm/Objects}/World.cs (78%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs rename frameworks/CSharp/appmpower/src/{ => appMpower.Orm/Serializers}/WorldSerializer.cs (68%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs rename frameworks/CSharp/appmpower/src/{appMpower.csproj => appMpower.Orm/appMpower.Orm.csproj} (52%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Program.cs rename frameworks/CSharp/appmpower/src/{Kestrel => appMpower/Serializers}/IJsonSerializer.cs (81%) rename frameworks/CSharp/appmpower/src/{ => appMpower/Serializers}/JsonMessageSerializer.cs (58%) create mode 100644 frameworks/CSharp/appmpower/src/appMpower/Startup.cs create mode 100644 frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj create mode 100644 frameworks/CSharp/appmpower/src/appMpower/appsettings.json rename frameworks/CSharp/appmpower/src/{ => appMpower}/nuget.config (100%) create mode 100644 frameworks/CSharp/appmpower/src/src.sln diff --git a/frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile b/frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile deleted file mode 100644 index 2e7234ca98d..00000000000 --- a/frameworks/CSharp/appmpower/appmpower-ado-pg.dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build -RUN apt-get update -RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5 - -WORKDIR /app -COPY src . -RUN dotnet publish -c Release -o out /p:Driver=ado - -# Construct the actual image that will run -FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime - -WORKDIR /app -COPY --from=build /app/out ./ - -EXPOSE 8080 - -ENTRYPOINT ["./appMpower"] \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile b/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile new file mode 100644 index 00000000000..a5bbf22ae6f --- /dev/null +++ b/frameworks/CSharp/appmpower/appmpower-odbc-my.dockerfile @@ -0,0 +1,51 @@ +FROM mcr.microsoft.com/dotnet/sdk:8.0.100 AS build +RUN apt-get update +RUN apt-get -yqq install clang zlib1g-dev +RUN apt-get update + +WORKDIR /app +COPY src . +RUN dotnet publish -c Release -o out /p:Database=mysql + +# Construct the actual image that will run +FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime + +RUN apt-get update +# The following installs standard versions unixodbc and pgsqlodbc +# unixodbc still needs to be installed even if compiled locally +RUN apt-get install -y unixodbc wget curl +RUN apt-get update + +WORKDIR /odbc + +RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz +RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz +RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb/libm* /usr/lib/ +RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-amd64/lib/mariadb /usr/local/lib/mariadb +RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-amd64.tar.gz +#TODOLOCAL +#RUN curl -L -o mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz https://downloads.mariadb.com/Connectors/odbc/connector-odbc-3.1.20/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz +#RUN tar -xvzf mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz +#RUN cp mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb/libm* /usr/lib/ +#RUN cp -r /odbc/mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64/lib/mariadb /usr/local/lib/mariadb +#RUN rm mariadb-connector-odbc-3.1.20-debian-bookworm-aarch64.tar.gz + +ENV PATH=/usr/local/unixODBC/bin:$PATH + +WORKDIR /etc/ +COPY odbcinst.ini . + +# Full PGO +ENV DOTNET_TieredPGO 1 +ENV DOTNET_TC_QuickJitForLoops 1 +ENV DOTNET_ReadyToRun 0 + +ENV ASPNETCORE_URLS http://+:8080 +WORKDIR /app +COPY --from=build /app/out ./ + +RUN cp /usr/lib/libm* /app + +EXPOSE 8080 + +ENTRYPOINT ["./appMpower"] \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile b/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile index c06865cc0b2..4080684bab6 100644 --- a/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile +++ b/frameworks/CSharp/appmpower/appmpower-odbc-pg.dockerfile @@ -4,7 +4,7 @@ RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5 WORKDIR /app COPY src . -RUN dotnet publish -c Release -o out /p:Driver=odbc +RUN dotnet publish -c Release -o out /p:Database=postgresql # Construct the actual image that will run FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime @@ -18,6 +18,12 @@ ENV PATH=/usr/local/unixODBC/bin:$PATH WORKDIR /etc/ COPY odbcinst.ini . +# Full PGO +ENV DOTNET_TieredPGO 1 +ENV DOTNET_TC_QuickJitForLoops 1 +ENV DOTNET_ReadyToRun 0 + +ENV ASPNETCORE_URLS http://+:8080 WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/appmpower/appmpower.dockerfile b/frameworks/CSharp/appmpower/appmpower.dockerfile index 7f77873dfaf..3d521c490d8 100644 --- a/frameworks/CSharp/appmpower/appmpower.dockerfile +++ b/frameworks/CSharp/appmpower/appmpower.dockerfile @@ -4,11 +4,17 @@ RUN apt-get -yqq install clang zlib1g-dev libkrb5-dev libtinfo5 WORKDIR /app COPY src . +#RUN dotnet publish appMpower/appMpower.csproj -c Release -o out RUN dotnet publish -c Release -o out # Construct the actual image that will run FROM mcr.microsoft.com/dotnet/aspnet:8.0.0 AS runtime +# Full PGO +ENV DOTNET_TieredPGO 1 +ENV DOTNET_TC_QuickJitForLoops 1 +ENV DOTNET_ReadyToRun 0 +ENV ASPNETCORE_URLS http://+:8080 WORKDIR /app COPY --from=build /app/out ./ diff --git a/frameworks/CSharp/appmpower/benchmark_config.json b/frameworks/CSharp/appmpower/benchmark_config.json index 6c22c0c65af..46dc7e7c00f 100644 --- a/frameworks/CSharp/appmpower/benchmark_config.json +++ b/frameworks/CSharp/appmpower/benchmark_config.json @@ -39,11 +39,11 @@ "webserver": "Kestrel", "os": "Linux", "database_os": "Linux", - "display_name": "appMpower [aot-no-reflection,odbc]", + "display_name": "appMpower [aot-no-reflection,pg,odbc]", "notes": "", "versus": "aspnetcore-minimal" }, - "ado-pg": { + "odbc-my": { "db_url": "/db", "query_url": "/queries?c=", "update_url": "/updates?c=", @@ -52,7 +52,7 @@ "port": 8080, "approach": "Realistic", "classification": "Platform", - "database": "Postgres", + "database": "MySQL", "framework": "appmpower", "language": "C#", "orm": "Raw", @@ -61,7 +61,7 @@ "webserver": "Kestrel", "os": "Linux", "database_os": "Linux", - "display_name": "appMpower [aot-no-reflection,ado]", + "display_name": "appMpower [aot-no-reflection,my,odbc]", "notes": "", "versus": "aspnetcore-minimal" } diff --git a/frameworks/CSharp/appmpower/config.toml b/frameworks/CSharp/appmpower/config.toml index d500b2df989..a3747682191 100644 --- a/frameworks/CSharp/appmpower/config.toml +++ b/frameworks/CSharp/appmpower/config.toml @@ -30,7 +30,7 @@ platform = ".NET" webserver = "Kestrel" versus = "aspnetcore-minimal" -[ado-pg] +[odbc-my] urls.db = "/db" urls.query = "/queries?c=" urls.update = "/updates?c=" @@ -38,7 +38,7 @@ urls.fortune = "/fortunes" urls.cached_query = "/cached-worlds?c=" approach = "Realistic" classification = "Micro" -database = "Postgres" +database = "MySQL" database_os = "Linux" os = "Linux" orm = "Raw" diff --git a/frameworks/CSharp/appmpower/odbcinst.ini b/frameworks/CSharp/appmpower/odbcinst.ini index c6260e38b93..544ba2067c1 100644 --- a/frameworks/CSharp/appmpower/odbcinst.ini +++ b/frameworks/CSharp/appmpower/odbcinst.ini @@ -5,6 +5,7 @@ Pooling=0 [ODBC Drivers] PostgreSQL = Installed +MariaDB = Installed ; ; odbcinst.ini @@ -15,7 +16,16 @@ Description=ODBC for PostgreSQL ; in version 08.x. Note that the library can also be installed under an other ; path than /usr/local/lib/ following your installation. ; This is the standard location used by apt-get install -y unixodbc +;ON SERVER Driver = /usr/lib/x86_64-linux-gnu/odbc/psqlodbcw.so +;TODOLOCAL: ON MAC +;Driver =/usr/lib/aarch64-linux-gnu/odbc/psqlodbcw.so + ;Driver =/usr/local/pgsqlodbc/lib/psqlodbcw.so Threading = 0 CPTimeout = 0 + +[MariaDB] +Description=MariaDB ODBC for MySQL +Driver = /usr/lib/libmaodbc.so +Threading = 0 \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs b/frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs deleted file mode 100644 index f7c78b6dd65..00000000000 --- a/frameworks/CSharp/appmpower/src/CachedWorldSerializer.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Text.Json; - -namespace appMpower -{ - public class CachedWorldSerializer : Kestrel.IJsonSerializer - { - public void Serialize(Utf8JsonWriter utf8JsonWriter, CachedWorld world) - { - utf8JsonWriter.WriteStartObject(); - utf8JsonWriter.WriteNumber("id", world.Id); - utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber); - utf8JsonWriter.WriteEndObject(); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Data/DbConnection.cs b/frameworks/CSharp/appmpower/src/Data/DbConnection.cs deleted file mode 100644 index 916e251a9c8..00000000000 --- a/frameworks/CSharp/appmpower/src/Data/DbConnection.cs +++ /dev/null @@ -1,200 +0,0 @@ -using System.Collections.Concurrent; -using System.Data; -using System.Threading.Tasks; - -namespace appMpower.Data -{ - public class DbConnection : IDbConnection - { - private string _connectionString; - internal InternalConnection _internalConnection; - - public DbConnection() - { - _connectionString = DbProviderFactory.ConnectionString; - } - - public DbConnection(string connectionString) - { - _connectionString = connectionString; - } - - internal ConcurrentDictionary DbCommands - { - get - { - return _internalConnection.DbCommands; - } - set - { - _internalConnection.DbCommands = value; - } - } - - public short Number - { - get - { - return _internalConnection.Number; - } - set - { - _internalConnection.Number = value; - } - } - - public IDbConnection Connection - { - get - { - return _internalConnection.DbConnection; - } - set - { - _internalConnection.DbConnection = value; - } - } - - public string ConnectionString - { - get - { - return _internalConnection.DbConnection.ConnectionString; - } - set - { - _internalConnection.DbConnection.ConnectionString = value; - } - } - - public int ConnectionTimeout - { - get - { - return _internalConnection.DbConnection.ConnectionTimeout; - } - } - - public string Database - { - get - { - return _internalConnection.DbConnection.Database; - } - } - - public ConnectionState State - { - get - { - if (_internalConnection is null) return ConnectionState.Closed; - return _internalConnection.DbConnection.State; - } - } - - public IDbTransaction BeginTransaction() - { - return _internalConnection.DbConnection.BeginTransaction(); - } - - public IDbTransaction BeginTransaction(IsolationLevel il) - { - return _internalConnection.DbConnection.BeginTransaction(il); - } - - public void ChangeDatabase(string databaseName) - { - _internalConnection.DbConnection.ChangeDatabase(databaseName); - } - - public void Close() - { - _internalConnection.DbConnection.Close(); - } - - public async Task CloseAsync() - { - await (_internalConnection.DbConnection as System.Data.Common.DbConnection).CloseAsync(); - } - - public IDbCommand CreateCommand() - { - return _internalConnection.DbConnection.CreateCommand(); - } - - public void Open() - { - if (_internalConnection.DbConnection.State == ConnectionState.Closed) - { - _internalConnection.DbConnection.Open(); - } - } - - public void Dispose() - { -#if ADO - _internalConnection.DbConnection.Dispose(); - _internalConnection.Dispose(); -#else - DbConnections.Release(_internalConnection); -#endif - } - - public async Task OpenAsync() - { -#if ADO && POSTGRESQL - _internalConnection = new(); - _internalConnection.DbConnection = new Npgsql.NpgsqlConnection(_connectionString); -#else - if (_internalConnection is null) - { - _internalConnection = await DbConnections.GetConnection(_connectionString); - } -#endif - - if (_internalConnection.DbConnection.State == ConnectionState.Closed) - { - await (_internalConnection.DbConnection as System.Data.Common.DbConnection).OpenAsync(); - } - } - - internal DbCommand GetCommand(string commandText, CommandType commandType, DbCommand dbCommand) - { -#if ADO - dbCommand.Command = _internalConnection.DbConnection.CreateCommand(); - dbCommand.Command.CommandText = commandText; - dbCommand.Command.CommandType = commandType; - dbCommand.DbConnection = this; -#else - DbCommand internalCommand; - - if (_internalConnection.DbCommands.TryRemove(commandText, out internalCommand)) - { - dbCommand.Command = internalCommand.Command; - dbCommand.DbConnection = internalCommand.DbConnection; - } - else - { - dbCommand.Command = _internalConnection.DbConnection.CreateCommand(); - dbCommand.Command.CommandText = commandText; - dbCommand.Command.CommandType = commandType; - dbCommand.DbConnection = this; - - //For non odbc drivers like Npgsql which do not support Prepare - dbCommand.Command.Prepare(); - - //Console.WriteLine("prepare pool connection: " + this._internalConnection.Number + " for command " + _internalConnection.DbCommands.Count); - } -#endif - - return dbCommand; - } - - public void ReleaseCommand(DbCommand dbCommand) - { -#if !ADO - _internalConnection.DbCommands.TryAdd(dbCommand.CommandText, dbCommand); -#endif - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Data/DbConnections.cs b/frameworks/CSharp/appmpower/src/Data/DbConnections.cs deleted file mode 100644 index 0b513a3d47f..00000000000 --- a/frameworks/CSharp/appmpower/src/Data/DbConnections.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System.Collections.Concurrent; -using System.Threading.Tasks; - -namespace appMpower.Data -{ - public static class DbConnections - { - private static bool _connectionsCreated = false; - private static short _createdConnections = 0; - private static short _maxConnections = 500; - - private static ConcurrentStack _stack = new(); - private static ConcurrentQueue> _waitingQueue = new(); - - public static async Task GetConnection(string connectionString) - { - InternalConnection internalConnection = null; - - if (_connectionsCreated) - { - if (!_stack.TryPop(out internalConnection)) - { - internalConnection = await GetDbConnectionAsync(); - } - - return internalConnection; - } - else - { - internalConnection = new InternalConnection(); - internalConnection.DbConnection = new System.Data.Odbc.OdbcConnection(connectionString); - - _createdConnections++; - - if (_createdConnections == _maxConnections) _connectionsCreated = true; - - internalConnection.Number = _createdConnections; - internalConnection.DbCommands = new ConcurrentDictionary(); - //Console.WriteLine("opened connection number: " + dbConnection.Number); - - return internalConnection; - } - } - - public static Task GetDbConnectionAsync() - { - var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - _waitingQueue.Enqueue(taskCompletionSource); - return taskCompletionSource.Task; - } - - public static void Release(InternalConnection internalConnection) - { - TaskCompletionSource taskCompletionSource; - - if (_waitingQueue.TryDequeue(out taskCompletionSource)) - { - taskCompletionSource.SetResult(internalConnection); - } - else - { - _stack.Push(internalConnection); - } - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs b/frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs deleted file mode 100644 index 98a4aa67cb6..00000000000 --- a/frameworks/CSharp/appmpower/src/Data/DbProviderFactory.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Data; - -namespace appMpower.Data -{ - public static class DbProviderFactory - { -#if MYSQL - public const string ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1"; -#elif ADO - public const string ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=0;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; - //public const string ConnectionString = "Server=localhost;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;SSL Mode=Disable;Maximum Pool Size=18;NoResetOnClose=true;Enlist=false;Max Auto Prepare=4;Multiplexing=true;Write Coalescing Buffer Threshold Bytes=1000"; -#else - public const string ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false"; - //public const string ConnectionString = "Driver={PostgreSQL};Server=localhost;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false"; -#endif - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Data/InternalConnection.cs b/frameworks/CSharp/appmpower/src/Data/InternalConnection.cs deleted file mode 100644 index 25cecfeb4f8..00000000000 --- a/frameworks/CSharp/appmpower/src/Data/InternalConnection.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Concurrent; -using System.Data; - -namespace appMpower.Data -{ - public class InternalConnection : System.IDisposable - { - public short Number { get; set; } - public IDbConnection DbConnection { get; set; } - public ConcurrentDictionary DbCommands { get; set; } - - public void Dispose() - { - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/HttpApplication.cs b/frameworks/CSharp/appmpower/src/HttpApplication.cs deleted file mode 100644 index 1eac250ede5..00000000000 --- a/frameworks/CSharp/appmpower/src/HttpApplication.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Text; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting.Server; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Features; -using appMpower.Kestrel; - -namespace appMpower -{ - public class HttpApplication : IHttpApplication - { - public static readonly byte[] _plainText = Encoding.UTF8.GetBytes("Hello, World!"); - private readonly static JsonMessageSerializer _jsonMessageSerializer = new JsonMessageSerializer(); - private readonly static WorldSerializer _worldSerializer = new WorldSerializer(); - private readonly static CachedWorldSerializer _cachedWorldSerializer = new CachedWorldSerializer(); - - public IFeatureCollection CreateContext(IFeatureCollection featureCollection) - { - return featureCollection; - } - - public async Task ProcessRequestAsync(IFeatureCollection featureCollection) - { - var request = featureCollection as IHttpRequestFeature; - var httpResponse = featureCollection as IHttpResponseFeature; - var httpResponseBody = featureCollection as IHttpResponseBodyFeature; - - PathString pathString = request.Path; - - if (pathString.HasValue) - { - int pathStringLength = pathString.Value.Length; - string pathStringStart = pathString.Value.Substring(1, 1); - - if (pathStringLength == 10 && pathStringStart == "p") - { - //await PlainText.RenderAsync(httpResponse.Headers, httpResponseBody.Writer, _plainText); - PlainText.Render(httpResponse.Headers, httpResponseBody, _plainText); - return; - } - else if (pathStringLength == 5 && pathStringStart == "j") - { - Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, new JsonMessage { message = "Hello, World!" }, _jsonMessageSerializer); - return; - } - else if (pathStringLength == 3 && pathStringStart == "d") - { - Json.RenderOne(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadSingleQueryRow(), _worldSerializer); - return; - } - else if (pathStringLength == 8 && pathStringStart == "q") - { - int count = 1; - - if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1) - { - count = 1; - } - else if (count > 500) - { - count = 500; - } - -#if ADO - Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleQueriesRows(count), _worldSerializer); -#else - Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.ReadMultipleRows(count), _worldSerializer); -#endif - - return; - } - else if (pathStringLength == 9 && pathStringStart == "f") - { - await FortunesView.Render(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadFortunesRows()); - return; - } - else if (pathStringLength == 8 && pathStringStart == "u") - { - int count = 1; - - if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1) - { - count = 1; - } - else if (count > 500) - { - count = 500; - } - - Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadMultipleUpdatesRows(count), _worldSerializer); - return; - } - else if (pathStringLength == 14 && pathStringStart == "c") - { - int count = 1; - - if (!Int32.TryParse(request.QueryString.Substring(request.QueryString.LastIndexOf("=") + 1), out count) || count < 1) - { - count = 1; - } - else if (count > 500) - { - count = 500; - } - - Json.RenderMany(httpResponse.Headers, httpResponseBody.Writer, await RawDb.LoadCachedQueries(count), _cachedWorldSerializer); - return; - } - } - } - - public void DisposeContext(IFeatureCollection featureCollection, Exception exception) - { - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/JsonMessage.cs b/frameworks/CSharp/appmpower/src/JsonMessage.cs deleted file mode 100644 index 24b78265baa..00000000000 --- a/frameworks/CSharp/appmpower/src/JsonMessage.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace appMpower -{ - public struct JsonMessage - { - public string message { get; set; } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Kestrel/Json.cs b/frameworks/CSharp/appmpower/src/Kestrel/Json.cs deleted file mode 100644 index c81028e2a9b..00000000000 --- a/frameworks/CSharp/appmpower/src/Kestrel/Json.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO.Pipelines; -using System.Text.Json; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; - -namespace appMpower.Kestrel -{ - public static class Json - { - private readonly static KeyValuePair _headerServer = - new KeyValuePair("Server", "k"); - private readonly static KeyValuePair _headerContentType = - new KeyValuePair("Content-Type", "application/json"); - - [ThreadStatic] - private static Utf8JsonWriter _utf8JsonWriter; - - public static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions - { - SkipValidation = true - }; - - public static void RenderOne(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T t, IJsonSerializer jsonSerializer) - { - headerDictionary.Add(_headerServer); - headerDictionary.Add(_headerContentType); - - Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(pipeWriter); - - jsonSerializer.Serialize(utf8JsonWriter, t); - utf8JsonWriter.Flush(); - headerDictionary.Add(new KeyValuePair("Content-Length", utf8JsonWriter.BytesCommitted.ToString())); - } - - public static void RenderMany(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, T[] tArray, IJsonSerializer jsonSerializer) - { - headerDictionary.Add(_headerServer); - headerDictionary.Add(_headerContentType); - - Utf8JsonWriter utf8JsonWriter = _utf8JsonWriter ??= new Utf8JsonWriter(pipeWriter, new JsonWriterOptions { SkipValidation = true }); - utf8JsonWriter.Reset(pipeWriter); - - utf8JsonWriter.WriteStartArray(); - - foreach (var t in tArray) - { - jsonSerializer.Serialize(utf8JsonWriter, t); - } - - utf8JsonWriter.WriteEndArray(); - utf8JsonWriter.Flush(); - headerDictionary.Add(new KeyValuePair("Content-Length", utf8JsonWriter.BytesCommitted.ToString())); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs b/frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs deleted file mode 100644 index e7ead33aa2e..00000000000 --- a/frameworks/CSharp/appmpower/src/Kestrel/PlainText.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Threading.Tasks; -using System.Collections.Generic; -using System.IO.Pipelines; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; -using Microsoft.AspNetCore.Http.Features; - -namespace appMpower.Kestrel -{ - public static class PlainText - { - private readonly static KeyValuePair _headerServer = - new KeyValuePair("Server", new StringValues("k")); - private readonly static KeyValuePair _headerContentType = - new KeyValuePair("Content-Type", new StringValues("text/plain")); - - public static async Task RenderAsync(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, ReadOnlyMemory utf8String) - { - headerDictionary.Add(_headerServer); - headerDictionary.Add(_headerContentType); - headerDictionary.Add(new KeyValuePair("Content-Length", utf8String.Length.ToString())); - - await pipeWriter.WriteAsync(utf8String); - pipeWriter.Complete(); - } - - public static void Render(IHeaderDictionary headerDictionary, IHttpResponseBodyFeature httpResponseBodyFeature, byte[] utf8String) - { - headerDictionary.Add(_headerServer); - headerDictionary.Add(_headerContentType); - int length = utf8String.Length; - headerDictionary.Add(new KeyValuePair("Content-Length", length.ToString())); - - httpResponseBodyFeature.Stream.Write(utf8String, 0, length); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs b/frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs deleted file mode 100644 index 513174e68b9..00000000000 --- a/frameworks/CSharp/appmpower/src/Kestrel/ServiceProvider.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace appMpower.Kestrel -{ - public class ServiceProvider : ISupportRequiredService, IServiceProvider - { - public object GetRequiredService(Type serviceType) - { - return GetService(serviceType); - } - - public object GetService(Type serviceType) - { - if (serviceType == typeof(ILoggerFactory)) - { - return NullLoggerFactory.Instance; - } - - return null; - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs b/frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs deleted file mode 100644 index 55ca29c4984..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/CacheEntry.cs +++ /dev/null @@ -1,257 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Primitives; -using Microsoft.Extensions.Caching.Memory; - -namespace appMpower.Memory -{ - internal sealed partial class CacheEntry : ICacheEntry - { - private static readonly Action ExpirationCallback = ExpirationTokensExpired; - - private readonly MemoryCache _cache; - - private CacheEntryTokens _tokens; // might be null if user is not using the tokens or callbacks - private TimeSpan? _absoluteExpirationRelativeToNow; - private TimeSpan? _slidingExpiration; - private long? _size; - private CacheEntry _previous; // this field is not null only before the entry is added to the cache and tracking is enabled - private object _value; - private CacheEntryState _state; - - internal CacheEntry(object key, MemoryCache memoryCache) - { - Key = key ?? throw new ArgumentNullException(nameof(key)); - _cache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache)); - _previous = memoryCache.TrackLinkedCacheEntries ? CacheEntryHelper.EnterScope(this) : null; - _state = new CacheEntryState(CacheItemPriority.Normal); - } - - /// - /// Gets or sets an absolute expiration date for the cache entry. - /// - public DateTimeOffset? AbsoluteExpiration { get; set; } - - /// - /// Gets or sets an absolute expiration time, relative to now. - /// - public TimeSpan? AbsoluteExpirationRelativeToNow - { - get => _absoluteExpirationRelativeToNow; - set - { - // this method does not set AbsoluteExpiration as it would require calling Clock.UtcNow twice: - // once here and once in MemoryCache.SetEntry - - if (value <= TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException( - nameof(AbsoluteExpirationRelativeToNow), - value, - "The relative expiration value must be positive."); - } - - _absoluteExpirationRelativeToNow = value; - } - } - - /// - /// Gets or sets how long a cache entry can be inactive (e.g. not accessed) before it will be removed. - /// This will not extend the entry lifetime beyond the absolute expiration (if set). - /// - public TimeSpan? SlidingExpiration - { - get => _slidingExpiration; - set - { - if (value <= TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException( - nameof(SlidingExpiration), - value, - "The sliding expiration value must be positive."); - } - - _slidingExpiration = value; - } - } - - /// - /// Gets the instances which cause the cache entry to expire. - /// - public IList ExpirationTokens => GetOrCreateTokens().ExpirationTokens; - - /// - /// Gets or sets the callbacks will be fired after the cache entry is evicted from the cache. - /// - public IList PostEvictionCallbacks => GetOrCreateTokens().PostEvictionCallbacks; - - /// - /// Gets or sets the priority for keeping the cache entry in the cache during a - /// memory pressure triggered cleanup. The default is . - /// - public CacheItemPriority Priority { get => _state.Priority; set => _state.Priority = value; } - - /// - /// Gets or sets the size of the cache entry value. - /// - public long? Size - { - get => _size; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative."); - } - - _size = value; - } - } - - public object Key { get; private set; } - - public object Value - { - get => _value; - set - { - _value = value; - _state.IsValueSet = true; - } - } - - internal DateTimeOffset LastAccessed { get; set; } - - internal EvictionReason EvictionReason { get => _state.EvictionReason; private set => _state.EvictionReason = value; } - - public void Dispose() - { - if (!_state.IsDisposed) - { - _state.IsDisposed = true; - - if (_cache.TrackLinkedCacheEntries) - { - CacheEntryHelper.ExitScope(this, _previous); - } - - // Don't commit or propagate options if the CacheEntry Value was never set. - // We assume an exception occurred causing the caller to not set the Value successfully, - // so don't use this entry. - if (_state.IsValueSet) - { - _cache.SetEntry(this); - - if (_previous != null && CanPropagateOptions()) - { - PropagateOptions(_previous); - } - } - - _previous = null; // we don't want to root unnecessary objects - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling - internal bool CheckExpired(in DateTimeOffset now) - => _state.IsExpired - || CheckForExpiredTime(now) - || (_tokens != null && _tokens.CheckForExpiredTokens(this)); - - internal void SetExpired(EvictionReason reason) - { - if (EvictionReason == EvictionReason.None) - { - EvictionReason = reason; - } - _state.IsExpired = true; - _tokens?.DetachTokens(); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling - private bool CheckForExpiredTime(in DateTimeOffset now) - { - if (!AbsoluteExpiration.HasValue && !_slidingExpiration.HasValue) - { - return false; - } - - return FullCheck(now); - - bool FullCheck(in DateTimeOffset offset) - { - if (AbsoluteExpiration.HasValue && AbsoluteExpiration.Value <= offset) - { - SetExpired(EvictionReason.Expired); - return true; - } - - if (_slidingExpiration.HasValue - && (offset - LastAccessed) >= _slidingExpiration) - { - SetExpired(EvictionReason.Expired); - return true; - } - - return false; - } - } - - internal void AttachTokens() => _tokens?.AttachTokens(this); - - private static void ExpirationTokensExpired(object obj) - { - // start a new thread to avoid issues with callbacks called from RegisterChangeCallback - Task.Factory.StartNew(state => - { - var entry = (CacheEntry)state; - entry.SetExpired(EvictionReason.TokenExpired); - entry._cache.EntryExpired(entry); - }, obj, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - } - - internal void InvokeEvictionCallbacks() => _tokens?.InvokeEvictionCallbacks(this); - - // this simple check very often allows us to avoid expensive call to PropagateOptions(CacheEntryHelper.Current) - [MethodImpl(MethodImplOptions.AggressiveInlining)] // added based on profiling - internal bool CanPropagateOptions() => (_tokens != null && _tokens.CanPropagateTokens()) || AbsoluteExpiration.HasValue; - - internal void PropagateOptions(CacheEntry parent) - { - if (parent == null) - { - return; - } - - // Copy expiration tokens and AbsoluteExpiration to the cache entries hierarchy. - // We do this regardless of it gets cached because the tokens are associated with the value we'll return. - _tokens?.PropagateTokens(parent); - - if (AbsoluteExpiration.HasValue) - { - if (!parent.AbsoluteExpiration.HasValue || AbsoluteExpiration < parent.AbsoluteExpiration) - { - parent.AbsoluteExpiration = AbsoluteExpiration; - } - } - } - - private CacheEntryTokens GetOrCreateTokens() - { - if (_tokens != null) - { - return _tokens; - } - - CacheEntryTokens result = new CacheEntryTokens(); - return Interlocked.CompareExchange(ref _tokens, result, null) ?? result; - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs b/frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs deleted file mode 100644 index 71d07fe24c5..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/CacheEntryHelper.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Threading; - -namespace appMpower.Memory -{ - internal static class CacheEntryHelper - { - private static readonly AsyncLocal _current = new AsyncLocal(); - - internal static CacheEntry Current - { - get => _current.Value; - private set => _current.Value = value; - } - - internal static CacheEntry EnterScope(CacheEntry current) - { - CacheEntry previous = Current; - Current = current; - return previous; - } - - internal static void ExitScope(CacheEntry current, CacheEntry previous) - { - Debug.Assert(Current == current, "Entries disposed in invalid order"); - Current = previous; - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs b/frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs deleted file mode 100644 index 15d59ead9c1..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/CacheEntryState.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using Microsoft.Extensions.Caching.Memory; - -namespace appMpower.Memory -{ - internal sealed partial class CacheEntry - { - // this type exists just to reduce CacheEntry size by replacing many enum & boolean fields with one of a size of Int32 - private struct CacheEntryState - { - private byte _flags; - private byte _evictionReason; - private byte _priority; - - internal CacheEntryState(CacheItemPriority priority) : this() => _priority = (byte)priority; - - internal bool IsDisposed - { - get => ((Flags)_flags & Flags.IsDisposed) != 0; - set => SetFlag(Flags.IsDisposed, value); - } - - internal bool IsExpired - { - get => ((Flags)_flags & Flags.IsExpired) != 0; - set => SetFlag(Flags.IsExpired, value); - } - - internal bool IsValueSet - { - get => ((Flags)_flags & Flags.IsValueSet) != 0; - set => SetFlag(Flags.IsValueSet, value); - } - - internal EvictionReason EvictionReason - { - get => (EvictionReason)_evictionReason; - set => _evictionReason = (byte)value; - } - - internal CacheItemPriority Priority - { - get => (CacheItemPriority)_priority; - set => _priority = (byte)value; - } - - private void SetFlag(Flags option, bool value) => _flags = (byte)(value ? (_flags | (byte)option) : (_flags & ~(byte)option)); - - [Flags] - private enum Flags : byte - { - Default = 0, - IsValueSet = 1 << 0, - IsExpired = 1 << 1, - IsDisposed = 1 << 2, - } - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs b/frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs deleted file mode 100644 index 247630639e7..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/CacheEntryTokens.cs +++ /dev/null @@ -1,140 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Primitives; -using Microsoft.Extensions.Caching.Memory; - -namespace appMpower.Memory -{ - internal sealed partial class CacheEntry - { - // this type exists just to reduce average CacheEntry size - // which typically is not using expiration tokens or callbacks - private sealed class CacheEntryTokens - { - private List _expirationTokens; - private List _expirationTokenRegistrations; - private List _postEvictionCallbacks; // this is not really related to tokens, but was moved here to shrink typical CacheEntry size - - internal List ExpirationTokens => _expirationTokens ??= new List(); - internal List PostEvictionCallbacks => _postEvictionCallbacks ??= new List(); - - internal void AttachTokens(CacheEntry cacheEntry) - { - if (_expirationTokens != null) - { - lock (this) - { - for (int i = 0; i < _expirationTokens.Count; i++) - { - IChangeToken expirationToken = _expirationTokens[i]; - if (expirationToken.ActiveChangeCallbacks) - { - _expirationTokenRegistrations ??= new List(1); - IDisposable registration = expirationToken.RegisterChangeCallback(ExpirationCallback, cacheEntry); - _expirationTokenRegistrations.Add(registration); - } - } - } - } - } - - internal bool CheckForExpiredTokens(CacheEntry cacheEntry) - { - if (_expirationTokens != null) - { - for (int i = 0; i < _expirationTokens.Count; i++) - { - IChangeToken expiredToken = _expirationTokens[i]; - if (expiredToken.HasChanged) - { - cacheEntry.SetExpired(EvictionReason.TokenExpired); - return true; - } - } - } - return false; - } - - internal bool CanPropagateTokens() => _expirationTokens != null; - - internal void PropagateTokens(CacheEntry parentEntry) - { - if (_expirationTokens != null) - { - lock (this) - { - lock (parentEntry.GetOrCreateTokens()) - { - foreach (IChangeToken expirationToken in _expirationTokens) - { - parentEntry.AddExpirationToken(expirationToken); - } - } - } - } - } - - internal void DetachTokens() - { - // _expirationTokenRegistrations is not checked for null, because AttachTokens might initialize it under lock - // instead we are checking for _expirationTokens, because if they are not null, then _expirationTokenRegistrations might also be not null - if (_expirationTokens != null) - { - lock (this) - { - List registrations = _expirationTokenRegistrations; - if (registrations != null) - { - _expirationTokenRegistrations = null; - for (int i = 0; i < registrations.Count; i++) - { - IDisposable registration = registrations[i]; - registration.Dispose(); - } - } - } - } - } - - internal void InvokeEvictionCallbacks(CacheEntry cacheEntry) - { - if (_postEvictionCallbacks != null) - { - Task.Factory.StartNew(state => InvokeCallbacks((CacheEntry)state), cacheEntry, - CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - } - } - - private static void InvokeCallbacks(CacheEntry entry) - { - List callbackRegistrations = Interlocked.Exchange(ref entry._tokens._postEvictionCallbacks, null); - - if (callbackRegistrations == null) - { - return; - } - - for (int i = 0; i < callbackRegistrations.Count; i++) - { - PostEvictionCallbackRegistration registration = callbackRegistrations[i]; - - try - { - registration.EvictionCallback?.Invoke(entry.Key, entry.Value, entry.EvictionReason, registration.State); - } - catch (Exception e) - { - // This will be invoked on a background thread, don't let it throw. - entry._cache._logger.LogError(e, "EvictionCallback invoked failed"); - } - } - } - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs b/frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs deleted file mode 100644 index df4f7063cf0..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/MemoryCache.cs +++ /dev/null @@ -1,520 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Caching.Memory; - -namespace appMpower.Memory -{ - /// - /// An implementation of using a dictionary to - /// store its entries. - /// - public class MemoryCache : IMemoryCache - { - internal readonly ILogger _logger; - - private readonly MemoryCacheOptions _options; - private readonly ConcurrentDictionary _entries; - - private long _cacheSize; - private bool _disposed; - private DateTimeOffset _lastExpirationScan; - - /// - /// Creates a new instance. - /// - /// The options of the cache. - public MemoryCache(IOptions optionsAccessor) - : this(optionsAccessor, NullLoggerFactory.Instance) { } - - /// - /// Creates a new instance. - /// - /// The options of the cache. - /// The factory used to create loggers. - public MemoryCache(IOptions optionsAccessor, ILoggerFactory loggerFactory) - { - if (optionsAccessor == null) - { - throw new ArgumentNullException(nameof(optionsAccessor)); - } - - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _options = optionsAccessor.Value; - //_logger = loggerFactory.CreateLogger(); - _logger = loggerFactory.CreateLogger("MemoryCache"); - - _entries = new ConcurrentDictionary(); - - if (_options.Clock == null) - { - _options.Clock = new SystemClock(); - } - - _lastExpirationScan = _options.Clock.UtcNow; - TrackLinkedCacheEntries = _options.TrackLinkedCacheEntries; // we store the setting now so it's consistent for entire MemoryCache lifetime - } - - /// - /// Cleans up the background collection events. - /// - ~MemoryCache() => Dispose(false); - - /// - /// Gets the count of the current entries for diagnostic purposes. - /// - public int Count => _entries.Count; - - // internal for testing - internal long Size { get => Interlocked.Read(ref _cacheSize); } - - internal bool TrackLinkedCacheEntries { get; } - - private ICollection> EntriesCollection => _entries; - - /// - public ICacheEntry CreateEntry(object key) - { - CheckDisposed(); - ValidateCacheKey(key); - - return new CacheEntry(key, this); - } - - internal void SetEntry(CacheEntry entry) - { - if (_disposed) - { - // No-op instead of throwing since this is called during CacheEntry.Dispose - return; - } - - if (_options.SizeLimit.HasValue && !entry.Size.HasValue) - { - //throw new InvalidOperationException(SR.Format(SR.CacheEntryHasEmptySize, nameof(entry.Size), nameof(_options.SizeLimit))); - throw new InvalidOperationException(); - } - - DateTimeOffset utcNow = _options.Clock.UtcNow; - - DateTimeOffset? absoluteExpiration = null; - if (entry.AbsoluteExpirationRelativeToNow.HasValue) - { - absoluteExpiration = utcNow + entry.AbsoluteExpirationRelativeToNow; - } - else if (entry.AbsoluteExpiration.HasValue) - { - absoluteExpiration = entry.AbsoluteExpiration; - } - - // Applying the option's absolute expiration only if it's not already smaller. - // This can be the case if a dependent cache entry has a smaller value, and - // it was set by cascading it to its parent. - if (absoluteExpiration.HasValue) - { - if (!entry.AbsoluteExpiration.HasValue || absoluteExpiration.Value < entry.AbsoluteExpiration.Value) - { - entry.AbsoluteExpiration = absoluteExpiration; - } - } - - // Initialize the last access timestamp at the time the entry is added - entry.LastAccessed = utcNow; - - if (_entries.TryGetValue(entry.Key, out CacheEntry priorEntry)) - { - priorEntry.SetExpired(EvictionReason.Replaced); - } - - bool exceedsCapacity = UpdateCacheSizeExceedsCapacity(entry); - - if (!entry.CheckExpired(utcNow) && !exceedsCapacity) - { - bool entryAdded = false; - - if (priorEntry == null) - { - // Try to add the new entry if no previous entries exist. - entryAdded = _entries.TryAdd(entry.Key, entry); - } - else - { - // Try to update with the new entry if a previous entries exist. - entryAdded = _entries.TryUpdate(entry.Key, entry, priorEntry); - - if (entryAdded) - { - if (_options.SizeLimit.HasValue) - { - // The prior entry was removed, decrease the by the prior entry's size - Interlocked.Add(ref _cacheSize, -priorEntry.Size.Value); - } - } - else - { - // The update will fail if the previous entry was removed after retrival. - // Adding the new entry will succeed only if no entry has been added since. - // This guarantees removing an old entry does not prevent adding a new entry. - entryAdded = _entries.TryAdd(entry.Key, entry); - } - } - - if (entryAdded) - { - entry.AttachTokens(); - } - else - { - if (_options.SizeLimit.HasValue) - { - // Entry could not be added, reset cache size - Interlocked.Add(ref _cacheSize, -entry.Size.Value); - } - entry.SetExpired(EvictionReason.Replaced); - entry.InvokeEvictionCallbacks(); - } - - if (priorEntry != null) - { - priorEntry.InvokeEvictionCallbacks(); - } - } - else - { - if (exceedsCapacity) - { - // The entry was not added due to overcapacity - entry.SetExpired(EvictionReason.Capacity); - - TriggerOvercapacityCompaction(); - } - else - { - if (_options.SizeLimit.HasValue) - { - // Entry could not be added due to being expired, reset cache size - Interlocked.Add(ref _cacheSize, -entry.Size.Value); - } - } - - entry.InvokeEvictionCallbacks(); - if (priorEntry != null) - { - RemoveEntry(priorEntry); - } - } - - StartScanForExpiredItemsIfNeeded(utcNow); - } - - /// - public bool TryGetValue(object key, out object result) - { - ValidateCacheKey(key); - CheckDisposed(); - - DateTimeOffset utcNow = _options.Clock.UtcNow; - - if (_entries.TryGetValue(key, out CacheEntry entry)) - { - // Check if expired due to expiration tokens, timers, etc. and if so, remove it. - // Allow a stale Replaced value to be returned due to concurrent calls to SetExpired during SetEntry. - if (!entry.CheckExpired(utcNow) || entry.EvictionReason == EvictionReason.Replaced) - { - entry.LastAccessed = utcNow; - result = entry.Value; - - if (TrackLinkedCacheEntries && entry.CanPropagateOptions()) - { - // When this entry is retrieved in the scope of creating another entry, - // that entry needs a copy of these expiration tokens. - entry.PropagateOptions(CacheEntryHelper.Current); - } - - StartScanForExpiredItemsIfNeeded(utcNow); - - return true; - } - else - { - // TODO: For efficiency queue this up for batch removal - RemoveEntry(entry); - } - } - - StartScanForExpiredItemsIfNeeded(utcNow); - - result = null; - return false; - } - - /// - public void Remove(object key) - { - ValidateCacheKey(key); - - CheckDisposed(); - if (_entries.TryRemove(key, out CacheEntry entry)) - { - if (_options.SizeLimit.HasValue) - { - Interlocked.Add(ref _cacheSize, -entry.Size.Value); - } - - entry.SetExpired(EvictionReason.Removed); - entry.InvokeEvictionCallbacks(); - } - - StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow); - } - - private void RemoveEntry(CacheEntry entry) - { - if (EntriesCollection.Remove(new KeyValuePair(entry.Key, entry))) - { - if (_options.SizeLimit.HasValue) - { - Interlocked.Add(ref _cacheSize, -entry.Size.Value); - } - entry.InvokeEvictionCallbacks(); - } - } - - internal void EntryExpired(CacheEntry entry) - { - // TODO: For efficiency consider processing these expirations in batches. - RemoveEntry(entry); - StartScanForExpiredItemsIfNeeded(_options.Clock.UtcNow); - } - - // Called by multiple actions to see how long it's been since we last checked for expired items. - // If sufficient time has elapsed then a scan is initiated on a background task. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void StartScanForExpiredItemsIfNeeded(DateTimeOffset utcNow) - { - if (_options.ExpirationScanFrequency < utcNow - _lastExpirationScan) - { - ScheduleTask(utcNow); - } - - void ScheduleTask(DateTimeOffset utcNow) - { - _lastExpirationScan = utcNow; - Task.Factory.StartNew(state => ScanForExpiredItems((MemoryCache)state), this, - CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - } - } - - private static void ScanForExpiredItems(MemoryCache cache) - { - DateTimeOffset now = cache._lastExpirationScan = cache._options.Clock.UtcNow; - - foreach (KeyValuePair item in cache._entries) - { - CacheEntry entry = item.Value; - - if (entry.CheckExpired(now)) - { - cache.RemoveEntry(entry); - } - } - } - - private bool UpdateCacheSizeExceedsCapacity(CacheEntry entry) - { - if (!_options.SizeLimit.HasValue) - { - return false; - } - - long newSize = 0L; - for (int i = 0; i < 100; i++) - { - long sizeRead = Interlocked.Read(ref _cacheSize); - newSize = sizeRead + entry.Size.Value; - - if (newSize < 0 || newSize > _options.SizeLimit) - { - // Overflow occurred, return true without updating the cache size - return true; - } - - if (sizeRead == Interlocked.CompareExchange(ref _cacheSize, newSize, sizeRead)) - { - return false; - } - } - - return true; - } - - private void TriggerOvercapacityCompaction() - { - _logger.LogDebug("Overcapacity compaction triggered"); - - // Spawn background thread for compaction - ThreadPool.QueueUserWorkItem(s => OvercapacityCompaction((MemoryCache)s), this); - } - - private static void OvercapacityCompaction(MemoryCache cache) - { - long currentSize = Interlocked.Read(ref cache._cacheSize); - - cache._logger.LogDebug($"Overcapacity compaction executing. Current size {currentSize}"); - - double? lowWatermark = cache._options.SizeLimit * (1 - cache._options.CompactionPercentage); - if (currentSize > lowWatermark) - { - cache.Compact(currentSize - (long)lowWatermark, entry => entry.Size.Value); - } - - cache._logger.LogDebug($"Overcapacity compaction executed. New size {Interlocked.Read(ref cache._cacheSize)}"); - } - - /// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy: - /// 1. Remove all expired items. - /// 2. Bucket by CacheItemPriority. - /// 3. Least recently used objects. - /// ?. Items with the soonest absolute expiration. - /// ?. Items with the soonest sliding expiration. - /// ?. Larger objects - estimated by object graph size, inaccurate. - public void Compact(double percentage) - { - int removalCountTarget = (int)(_entries.Count * percentage); - Compact(removalCountTarget, _ => 1); - } - - private void Compact(long removalSizeTarget, Func computeEntrySize) - { - var entriesToRemove = new List(); - var lowPriEntries = new List(); - var normalPriEntries = new List(); - var highPriEntries = new List(); - long removedSize = 0; - - // Sort items by expired & priority status - DateTimeOffset now = _options.Clock.UtcNow; - foreach (KeyValuePair item in _entries) - { - CacheEntry entry = item.Value; - if (entry.CheckExpired(now)) - { - entriesToRemove.Add(entry); - removedSize += computeEntrySize(entry); - } - else - { - switch (entry.Priority) - { - case CacheItemPriority.Low: - lowPriEntries.Add(entry); - break; - case CacheItemPriority.Normal: - normalPriEntries.Add(entry); - break; - case CacheItemPriority.High: - highPriEntries.Add(entry); - break; - case CacheItemPriority.NeverRemove: - break; - default: - throw new NotSupportedException("Not implemented: " + entry.Priority); - } - } - } - - ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, lowPriEntries); - ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, normalPriEntries); - ExpirePriorityBucket(ref removedSize, removalSizeTarget, computeEntrySize, entriesToRemove, highPriEntries); - - foreach (CacheEntry entry in entriesToRemove) - { - RemoveEntry(entry); - } - - // Policy: - // 1. Least recently used objects. - // ?. Items with the soonest absolute expiration. - // ?. Items with the soonest sliding expiration. - // ?. Larger objects - estimated by object graph size, inaccurate. - static void ExpirePriorityBucket(ref long removedSize, long removalSizeTarget, Func computeEntrySize, List entriesToRemove, List priorityEntries) - { - // Do we meet our quota by just removing expired entries? - if (removalSizeTarget <= removedSize) - { - // No-op, we've met quota - return; - } - - // Expire enough entries to reach our goal - // TODO: Refine policy - - // LRU - priorityEntries.Sort((e1, e2) => e1.LastAccessed.CompareTo(e2.LastAccessed)); - foreach (CacheEntry entry in priorityEntries) - { - entry.SetExpired(EvictionReason.Capacity); - entriesToRemove.Add(entry); - removedSize += computeEntrySize(entry); - - if (removalSizeTarget <= removedSize) - { - break; - } - } - } - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - GC.SuppressFinalize(this); - } - - _disposed = true; - } - } - - private void CheckDisposed() - { - if (_disposed) - { - Throw(); - } - - static void Throw() => throw new ObjectDisposedException(typeof(MemoryCache).FullName); - } - - private static void ValidateCacheKey(object key) - { - if (key == null) - { - Throw(); - } - - static void Throw() => throw new ArgumentNullException(nameof(key)); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs b/frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs deleted file mode 100644 index d714c96df42..00000000000 --- a/frameworks/CSharp/appmpower/src/Memory/MemoryCacheOptions.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using Microsoft.Extensions.Internal; -using Microsoft.Extensions.Options; - -namespace appMpower.Memory -{ - public class MemoryCacheOptions : IOptions - { - private long? _sizeLimit; - private double _compactionPercentage = 0.05; - - public ISystemClock Clock { get; set; } - - /// - /// Gets or sets the minimum length of time between successive scans for expired items. - /// - public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1); - - /// - /// Gets or sets the maximum size of the cache. - /// - public long? SizeLimit - { - get => _sizeLimit; - set - { - if (value < 0) - { - throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be non-negative."); - } - - _sizeLimit = value; - } - } - - /// - /// Gets or sets the amount to compact the cache by when the maximum size is exceeded. - /// - public double CompactionPercentage - { - get => _compactionPercentage; - set - { - if (value < 0 || value > 1) - { - throw new ArgumentOutOfRangeException(nameof(value), value, $"{nameof(value)} must be between 0 and 1 inclusive."); - } - - _compactionPercentage = value; - } - } - - /// - /// Gets or sets whether to track linked entries. Disabled by default. - /// - /// Prior to .NET 7 this feature was always enabled. - public bool TrackLinkedCacheEntries { get; set; } - - MemoryCacheOptions IOptions.Value - { - get { return this; } - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs b/frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs deleted file mode 100644 index 3bc21736c08..00000000000 --- a/frameworks/CSharp/appmpower/src/Microsoft/CachKey.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace PlatformBenchmarks -{ - public sealed class CacheKey : IEquatable - { - private readonly int _value; - - public CacheKey(int value) - => _value = value; - - public bool Equals(CacheKey key) - => key._value == _value; - - public override bool Equals(object obj) - => ReferenceEquals(obj, this); - - public override int GetHashCode() - => _value; - - public override string ToString() - => _value.ToString(); - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs b/frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs deleted file mode 100644 index 6f0b20b7278..00000000000 --- a/frameworks/CSharp/appmpower/src/Microsoft/StringBuilderCache.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Text; - -namespace PlatformBenchmarks -{ - internal static class StringBuilderCache - { - private const int DefaultCapacity = 1386; - private const int MaxBuilderSize = DefaultCapacity * 3; - - [ThreadStatic] - private static StringBuilder t_cachedInstance; - - /// Get a StringBuilder for the specified capacity. - /// If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied. - public static StringBuilder Acquire(int capacity = DefaultCapacity) - { - if (capacity <= MaxBuilderSize) - { - StringBuilder sb = t_cachedInstance; - if (capacity < DefaultCapacity) - { - capacity = DefaultCapacity; - } - - if (sb != null) - { - // Avoid stringbuilder block fragmentation by getting a new StringBuilder - // when the requested size is larger than the current capacity - if (capacity <= sb.Capacity) - { - t_cachedInstance = null; - sb.Clear(); - return sb; - } - } - } - return new StringBuilder(capacity); - } - - public static void Release(StringBuilder sb) - { - if (sb.Capacity <= MaxBuilderSize) - { - t_cachedInstance = sb; - } - } - - public static string GetStringAndRelease(StringBuilder sb) - { - string result = sb.ToString(); - Release(sb); - return result; - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Program.cs b/frameworks/CSharp/appmpower/src/Program.cs deleted file mode 100644 index 6e748b08497..00000000000 --- a/frameworks/CSharp/appmpower/src/Program.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Hosting.Server.Features; -using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; - -namespace appMpower -{ - class Program - { - static async Task Main(string[] args) - { - var socketTransportOptions = new SocketTransportOptions(); - var socketTransportFactory = new SocketTransportFactory(Options.Create(socketTransportOptions), NullLoggerFactory.Instance); - var kestrelServerOptions = new KestrelServerOptions(); - - kestrelServerOptions.Listen(IPAddress.Any, 8080); - kestrelServerOptions.AllowSynchronousIO = true; - kestrelServerOptions.AddServerHeader = false; - - using var kestrelServer = new KestrelServer(Options.Create(kestrelServerOptions), socketTransportFactory, NullLoggerFactory.Instance); - - await kestrelServer.StartAsync(new HttpApplication(), CancellationToken.None); - - Console.WriteLine("Listening on:"); - - foreach (var address in kestrelServer.Features.Get().Addresses) - { - Console.WriteLine(" - " + address); - } - - Console.WriteLine("Process CTRL+C to quit"); - var wh = new ManualResetEventSlim(); - Console.CancelKeyPress += (sender, e) => wh.Set(); - wh.Wait(); - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/RawDb.cs b/frameworks/CSharp/appmpower/src/RawDb.cs deleted file mode 100644 index 8813ce6dfcc..00000000000 --- a/frameworks/CSharp/appmpower/src/RawDb.cs +++ /dev/null @@ -1,331 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; -using appMpower.Data; -using PlatformBenchmarks; - -namespace appMpower -{ - public static class RawDb - { - private const int MaxBatch = 500; - -#if ADO - private static ConcurrentRandom _random = new ConcurrentRandom(); -#else - private static Random _random = new Random(); -#endif - - private static string[] _queriesMultipleRows = new string[MaxBatch + 1]; - - private static readonly object[] _cacheKeys = Enumerable.Range(0, 10001).Select((i) => new CacheKey(i)).ToArray(); - - private static readonly appMpower.Memory.MemoryCache _cache = new appMpower.Memory.MemoryCache( - new appMpower.Memory.MemoryCacheOptions() - { - ExpirationScanFrequency = TimeSpan.FromMinutes(60) - }); - - public static async Task LoadSingleQueryRow() - { - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var (dbCommand, _) = CreateReadCommand(pooledConnection); - - using (dbCommand) - { - var world = await ReadSingleRow(dbCommand); - - return world; - } - } - - public static async Task LoadMultipleQueriesRows(int count) - { - var worlds = new World[count]; - - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection); - - using (dbCommand) - { - for (int i = 0; i < count; i++) - { - worlds[i] = await ReadSingleRow(dbCommand); - dbDataParameter.Value = _random.Next(1, 10001); - } - } - - return worlds; - } - - public static async Task> LoadFortunesRows() - { - var fortunes = new List(); - - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var dbCommand = new DbCommand("SELECT * FROM fortune", pooledConnection); - - using (dbCommand) - { - var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess); - - while (dataReader.Read()) - { - fortunes.Add(new Fortune - ( - id: dataReader.GetInt32(0), -#if MYSQL - //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET; - //as a solution we custom read this string - message: ReadColumn(dataReader, 1) -#else - message: dataReader.GetString(1) -#endif - )); - } - - dataReader.Close(); - } - - fortunes.Add(new Fortune(id: 0, message: "Additional fortune added at request time.")); - fortunes.Sort(); - - return fortunes; - } - - public static async Task LoadMultipleUpdatesRows(int count) - { - var worlds = new World[count]; - - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var (queryCommand, dbDataParameter) = CreateReadCommand(pooledConnection); - - using (queryCommand) - { - for (int i = 0; i < count; i++) - { - worlds[i] = await ReadSingleRow(queryCommand); - dbDataParameter.Value = _random.Next(1, 10001); - } - } - - using var updateCommand = new DbCommand(PlatformBenchmarks.BatchUpdateString.Query(count), pooledConnection); - - var ids = PlatformBenchmarks.BatchUpdateString.Ids; - var randoms = PlatformBenchmarks.BatchUpdateString.Randoms; - -#if !MYSQL - var jds = PlatformBenchmarks.BatchUpdateString.Jds; -#endif - - for (int i = 0; i < count; i++) - { - var randomNumber = _random.Next(1, 10001); - - updateCommand.CreateParameter(ids[i], DbType.Int32, worlds[i].Id); - updateCommand.CreateParameter(randoms[i], DbType.Int32, randomNumber); - - worlds[i].RandomNumber = randomNumber; - } - -#if !MYSQL - for (int i = 0; i < count; i++) - { - updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id); - } -#endif - - await updateCommand.ExecuteNonQueryAsync(); - - return worlds; - } - - private static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection) - { -#if ADO - var dbCommand = new DbCommand("SELECT * FROM world WHERE id=@Id", pooledConnection); -#else - var dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection); -#endif - - return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001))); - } - - private static async Task ReadSingleRow(DbCommand dbCommand) - { - var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess); - - dataReader.Read(); - - var world = new World - { - Id = dataReader.GetInt32(0), - RandomNumber = dataReader.GetInt32(1) - }; - - dataReader.Close(); - - return world; - } - - public static async Task ReadMultipleRows(int count) - { - int j = 0; - var ids = PlatformBenchmarks.BatchUpdateString.Ids; - var worlds = new World[count]; - string queryString; - - if (_queriesMultipleRows[count] != null) - { - queryString = _queriesMultipleRows[count]; - } - else - { - var stringBuilder = PlatformBenchmarks.StringBuilderCache.Acquire(); - - for (int i = 0; i < count; i++) - { - stringBuilder.Append("SELECT * FROM world WHERE id=?;"); - } - - queryString = _queriesMultipleRows[count] = PlatformBenchmarks.StringBuilderCache.GetStringAndRelease(stringBuilder); - } - - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - using var dbCommand = new DbCommand(queryString, pooledConnection); - - for (int i = 0; i < count; i++) - { - dbCommand.CreateParameter(ids[i], DbType.Int32, _random.Next(1, 10001)); - } - - var dataReader = await dbCommand.ExecuteReaderAsync(CommandBehavior.Default & CommandBehavior.SequentialAccess); - - do - { - dataReader.Read(); - - worlds[j] = new World - { - Id = dataReader.GetInt32(0), - RandomNumber = dataReader.GetInt32(1) - }; - - j++; - } while (await dataReader.NextResultAsync()); - - dataReader.Close(); - - return worlds; - } - - public static string ReadColumn(IDataReader dataReader, int column) - { - long size = dataReader.GetBytes(column, 0, null, 0, 0); //get the length of data - byte[] values = new byte[size]; - - int bufferSize = 64; - long bytesRead = 0; - int currentPosition = 0; - - while (bytesRead < size) - { - bytesRead += dataReader.GetBytes(column, currentPosition, values, currentPosition, bufferSize); - currentPosition += bufferSize; - } - - return System.Text.Encoding.Default.GetString(values); - } - - public static async Task PopulateCache() - { - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection); - - using (dbCommand) - { - var cacheKeys = _cacheKeys; - var cache = _cache; - - for (var i = 1; i < 10001; i++) - { - dbDataParameter.Value = i; - cache.Set(cacheKeys[i], await ReadSingleRow(dbCommand)); - } - } - } - - public static Task LoadCachedQueries(int count) - { - var result = new CachedWorld[count]; - var cacheKeys = _cacheKeys; - var cache = _cache; - var random = _random; - - for (var i = 0; i < result.Length; i++) - { - var id = random.Next(1, 10001); - var key = cacheKeys[id]; - - if (cache.TryGetValue(key, out object cached)) - { - result[i] = (CachedWorld)cached; - } - else - { - //return LoadUncachedQueries(id, i, count, this, result); - return LoadUncachedQueries(id, i, count, result); - } - } - - return Task.FromResult(result); - } - - static async Task LoadUncachedQueries(int id, int i, int count, CachedWorld[] result) - { - using var pooledConnection = new DbConnection(DbProviderFactory.ConnectionString); - await pooledConnection.OpenAsync(); - - var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection); - - using (dbCommand) - { - Func> create = async (entry) => - { - return await ReadSingleRow(dbCommand); - }; - - var cacheKeys = _cacheKeys; - var key = cacheKeys[id]; - - dbDataParameter.Value = id; - - for (; i < result.Length; i++) - { - result[i] = await _cache.GetOrCreateAsync(key, create); - - id = _random.Next(1, 10001); - dbDataParameter.Value = id; - key = cacheKeys[id]; - } - } - - return result; - } - } -} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs new file mode 100644 index 00000000000..c1678a71a62 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Constants.cs @@ -0,0 +1,10 @@ +using appMpower.Orm.Data; + +namespace appMpower.Orm +{ + public static class Constants + { + public static Dbms Dbms = Dbms.PostgreSQL; + public static DbProvider DbProvider = DbProvider.ODBC; + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Data/DbCommand.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs similarity index 52% rename from frameworks/CSharp/appmpower/src/Data/DbCommand.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs index 2086068c802..a580aa5e110 100644 --- a/frameworks/CSharp/appmpower/src/Data/DbCommand.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbCommand.cs @@ -1,56 +1,46 @@ using System.Data; -using System.Threading.Tasks; +using System.Data.Odbc; -namespace appMpower.Data +namespace appMpower.Orm.Data { public class DbCommand : IDbCommand { - private IDbCommand _dbCommand; + private OdbcCommand _odbcCommand; private DbConnection _dbConnection; public DbCommand(DbConnection dbConnection) { - _dbCommand = dbConnection.CreateCommand(); + _odbcCommand = (OdbcCommand)dbConnection.CreateCommand(); _dbConnection = dbConnection; } public DbCommand(string commandText, DbConnection dbConnection) { - dbConnection.GetCommand(commandText, CommandType.Text, this); - } - - public DbCommand(string commandText, CommandType commandType, DbConnection dbConnection) - { - dbConnection.GetCommand(commandText, commandType, this); + _odbcCommand = dbConnection.GetCommand(commandText, CommandType.Text); + _dbConnection = dbConnection; } - internal DbCommand(IDbCommand dbCommand, DbConnection dbConnection) + public DbCommand(string commandText, DbConnection dbConnection, bool keyed) { - _dbCommand = dbCommand; + _odbcCommand = dbConnection.GetCommand(commandText, CommandType.Text, keyed); _dbConnection = dbConnection; } - internal IDbCommand Command + public DbCommand(string commandText, CommandType commandType, DbConnection dbConnection) { - get - { - return _dbCommand; - } - set - { - _dbCommand = value; - } + _odbcCommand = dbConnection.GetCommand(commandText, commandType); + _dbConnection = dbConnection; } - internal DbConnection DbConnection + internal IDbCommand Command { get { - return _dbConnection; + return _odbcCommand; } set { - _dbConnection = value; + _odbcCommand = (OdbcCommand)value; } } @@ -58,11 +48,11 @@ public string CommandText { get { - return _dbCommand.CommandText; + return _odbcCommand.CommandText; } set { - _dbCommand.CommandText = value; + _odbcCommand.CommandText = value; } } @@ -70,22 +60,22 @@ public int CommandTimeout { get { - return _dbCommand.CommandTimeout; + return _odbcCommand.CommandTimeout; } set { - _dbCommand.CommandTimeout = value; + _odbcCommand.CommandTimeout = value; } } public CommandType CommandType { get { - return _dbCommand.CommandType; + return _odbcCommand.CommandType; } set { - _dbCommand.CommandType = value; + _odbcCommand.CommandType = value; } } @@ -94,11 +84,11 @@ public IDbConnection? Connection { get { - return _dbCommand.Connection; + return _odbcCommand.Connection; } set { - _dbCommand.Connection = (IDbConnection?)value; + _odbcCommand.Connection = (OdbcConnection?)value; } } #nullable disable @@ -107,7 +97,7 @@ public IDataParameterCollection Parameters { get { - return _dbCommand.Parameters; + return _odbcCommand.Parameters; } } @@ -116,11 +106,11 @@ public IDbTransaction? Transaction { get { - return _dbCommand.Transaction; + return _odbcCommand.Transaction; } set { - _dbCommand.Transaction = (IDbTransaction?)value; + _odbcCommand.Transaction = (OdbcTransaction?)value; } } #nullable disable @@ -129,21 +119,21 @@ public UpdateRowSource UpdatedRowSource { get { - return _dbCommand.UpdatedRowSource; + return _odbcCommand.UpdatedRowSource; } set { - _dbCommand.UpdatedRowSource = value; + _odbcCommand.UpdatedRowSource = value; } } public void Cancel() { - _dbCommand.Cancel(); + _odbcCommand.Cancel(); } public IDbDataParameter CreateParameter() { - return _dbCommand.CreateParameter(); + return _odbcCommand.CreateParameter(); } public IDbDataParameter CreateParameter(string name, object value) @@ -153,21 +143,21 @@ public IDbDataParameter CreateParameter(string name, object value) public IDbDataParameter CreateParameter(string name, DbType dbType, object value) { - IDbDataParameter dbDataParameter = null; + IDbDataParameter dbDataParameter; - if (this.Parameters.Contains(name)) + if (_odbcCommand.Parameters.Contains(name)) { - dbDataParameter = this.Parameters[name] as IDbDataParameter; + dbDataParameter = _odbcCommand.Parameters[name]; dbDataParameter.Value = value; } else { - dbDataParameter = _dbCommand.CreateParameter(); + dbDataParameter = _odbcCommand.CreateParameter(); dbDataParameter.ParameterName = name; dbDataParameter.DbType = dbType; dbDataParameter.Value = value; - this.Parameters.Add(dbDataParameter); + _odbcCommand.Parameters.Add(dbDataParameter); } return dbDataParameter; @@ -175,51 +165,40 @@ public IDbDataParameter CreateParameter(string name, DbType dbType, object value public int ExecuteNonQuery() { - return _dbCommand.ExecuteNonQuery(); + return _odbcCommand.ExecuteNonQuery(); } public IDataReader ExecuteReader() { - return _dbCommand.ExecuteReader(); + return _odbcCommand.ExecuteReader(); } public async Task ExecuteNonQueryAsync() { - return await (_dbCommand as System.Data.Common.DbCommand).ExecuteNonQueryAsync(); - } - - public async Task ExecuteReaderAsync(CommandBehavior behavior) - { - return await (_dbCommand as System.Data.Common.DbCommand).ExecuteReaderAsync(behavior); + return await (_odbcCommand as System.Data.Common.DbCommand).ExecuteNonQueryAsync(); } public IDataReader ExecuteReader(CommandBehavior behavior) { - return _dbCommand.ExecuteReader(behavior); + return _odbcCommand.ExecuteReader(behavior); } #nullable enable public object? ExecuteScalar() { - return _dbCommand.ExecuteScalar(); - } -#nullable disable - -#nullable enable - public async Task ExecuteScalarAsync() - { - return await ((System.Data.Common.DbCommand)_dbCommand).ExecuteScalarAsync(); + return _odbcCommand.ExecuteScalar(); } #nullable disable public void Prepare() { - _dbCommand.Prepare(); + _odbcCommand.Prepare(); } public void Dispose() { - _dbConnection.ReleaseCommand(this); + if (_dbConnection._keyed) _dbConnection._keyedOdbcCommands.TryAdd(_odbcCommand.CommandText, _odbcCommand); + else _dbConnection._odbcCommands.Push(_odbcCommand); } } } \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs new file mode 100644 index 00000000000..ba3b6cf85b6 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnection.cs @@ -0,0 +1,153 @@ +using System.Collections.Concurrent; +using System.Data; +using System.Data.Odbc; + +namespace appMpower.Orm.Data +{ + public class DbConnection : IDbConnection + { + private string _connectionString; + internal bool _keyed = false; + internal int _number; + internal OdbcConnection _odbcConnection; + internal ConcurrentStack _odbcCommands = new(); + internal Dictionary _keyedOdbcCommands; + + public DbConnection() + { + _connectionString = DbProviderFactory.ConnectionString; + } + + public DbConnection(string connectionString) + { + _connectionString = connectionString; + } + + public IDbConnection Connection + { + get + { + return _odbcConnection; + } + set + { + _odbcConnection = (OdbcConnection)value; + } + } + + public string ConnectionString + { + get + { + return _odbcConnection.ConnectionString; + } + set + { + _odbcConnection.ConnectionString = value; + } + } + + public int ConnectionTimeout + { + get + { + return _odbcConnection.ConnectionTimeout; + } + } + + public string Database + { + get + { + return _odbcConnection.Database; + } + } + + public ConnectionState State + { + get + { + if (_odbcConnection is null) return ConnectionState.Closed; + return _odbcConnection.State; + } + } + + public IDbTransaction BeginTransaction() + { + return _odbcConnection.BeginTransaction(); + } + + public IDbTransaction BeginTransaction(IsolationLevel il) + { + return _odbcConnection.BeginTransaction(il); + } + + public void ChangeDatabase(string databaseName) + { + _odbcConnection.ChangeDatabase(databaseName); + } + + public void Close() + { + _odbcConnection.Close(); + } + + public IDbCommand CreateCommand() + { + return _odbcConnection.CreateCommand(); + } + + public void Open() + { + if (_odbcConnection is null) + { + DbConnections.GetConnection(_connectionString, this); + } + + if (_odbcConnection.State == ConnectionState.Closed) + { + _odbcConnection.Open(); + } + } + + public void Dispose() + { + DbConnections.Release(this); + } + + internal OdbcCommand GetCommand(string commandText, CommandType commandType, bool keyed = false) + { + OdbcCommand odbcCommand; + + if (_odbcCommands.TryPop(out odbcCommand)) + { + if (commandText != odbcCommand.CommandText) + { + odbcCommand.CommandText = commandText; + odbcCommand.Parameters.Clear(); + } + + return odbcCommand; + } + else if (_keyed && _keyedOdbcCommands.TryGetValue(commandText, out odbcCommand)) + { + return odbcCommand; + } + else + { + if (!_keyed && keyed) + { + _keyedOdbcCommands = new(); + _keyed = keyed; + } + + odbcCommand = _odbcConnection.CreateCommand(); + odbcCommand.CommandText = commandText; + odbcCommand.CommandType = commandType; + odbcCommand.Prepare(); + + return odbcCommand; + } + } + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs new file mode 100644 index 00000000000..514e2945d38 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbConnections.cs @@ -0,0 +1,61 @@ +using System.Collections.Concurrent; + +namespace appMpower.Orm.Data +{ + public static class DbConnections + { + private static short _createdConnections = 0; + private static ConcurrentStack _connectionsStack = new(); + + public static DbConnection GetConnection(string connectionString) + { + DbConnection popDbConnection; + + if (!_connectionsStack.TryPop(out popDbConnection)) + { + popDbConnection = new DbConnection(); + popDbConnection._odbcConnection = new System.Data.Odbc.OdbcConnection(connectionString); + + _createdConnections++; + popDbConnection._number = _createdConnections; + + if (_createdConnections % 25 == 0) + { + Console.WriteLine("Pooled connections created: " + _createdConnections.ToString()); + } + } + + return popDbConnection; + } + + + public static void GetConnection(string connectionString, DbConnection dbConnection) + { + DbConnection popDbConnection = null; + + if (_connectionsStack.TryPop(out popDbConnection)) + { + dbConnection._odbcConnection = popDbConnection._odbcConnection; + dbConnection._odbcCommands = popDbConnection._odbcCommands; + dbConnection._number = popDbConnection._number; + } + else + { + dbConnection._odbcConnection = new System.Data.Odbc.OdbcConnection(connectionString); + + _createdConnections++; + dbConnection._number = _createdConnections; + + if (_createdConnections % 25 == 0) + { + Console.WriteLine("Pooled connections created: " + _createdConnections.ToString()); + } + } + } + + public static void Release(DbConnection dbConnection) + { + _connectionsStack.Push(dbConnection); + } + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs new file mode 100644 index 00000000000..bf60750b52d --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProvider.cs @@ -0,0 +1,8 @@ +namespace appMpower.Orm.Data +{ + public enum DbProvider + { + ADO = 0, + ODBC = 1, + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs new file mode 100644 index 00000000000..1e72d164a25 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/DbProviderFactory.cs @@ -0,0 +1,21 @@ +using System.Data; + +namespace appMpower.Orm.Data +{ + public static class DbProviderFactory + { + public static string ConnectionString; + + public static void SetConnectionString() + { + if (Constants.Dbms == Dbms.MySQL) + { + ConnectionString = "Driver={MariaDB};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;Pooling=false;OPTIONS=67108864;FLAG_FORWARD_CURSOR=1;sslmode=DISABLED;CharSet=utf8;"; + } + else + { + ConnectionString = "Driver={PostgreSQL};Server=tfb-database;Database=hello_world;Uid=benchmarkdbuser;Pwd=benchmarkdbpass;UseServerSidePrepare=1;Pooling=false;sslmode=disable"; + } + } + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs new file mode 100644 index 00000000000..8c8bbeb67e6 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Data/Dbms.cs @@ -0,0 +1,9 @@ +namespace appMpower.Orm.Data +{ + public enum Dbms + { + MySQL = 0, + PostgreSQL = 1, + SQLServer = 2, + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs new file mode 100644 index 00000000000..f6b8b4cad1c --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/DotnetMethods.cs @@ -0,0 +1,66 @@ +using System.Runtime.InteropServices; +using System.Text; +using System.Text.Json; +using appMpower.Orm.Data; +using appMpower.Orm.Objects; +using appMpower.Orm.Serializers; + +namespace appMpower.Orm; + +//These methods are for test purposes only; not used in actual execution +public static class DotnetMethods +{ + private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions + { + Indented = false, + SkipValidation = true + }; + + private readonly static WorldSerializer _worldSerializer = new WorldSerializer(); + private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer(); + + public static byte[] Db() + { + var world = RawDb.LoadSingleQueryRow(); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldSerializer.Serialize(utf8JsonWriter, world); + + return memoryStream.ToArray(); + } + + public static byte[] Query(int queries) + { + World[] worlds = RawDb.ReadMultipleRows(queries); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldsSerializer.Serialize(utf8JsonWriter, worlds); + + return memoryStream.ToArray(); + } + + public static byte[] Updates(int count) + { + World[] worlds = RawDb.LoadMultipleUpdatesRows(count); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldsSerializer.Serialize(utf8JsonWriter, worlds); + + return memoryStream.ToArray(); + } + + public static byte[] Fortunes() + { + List fortunes = RawDb.LoadFortunesRows(); + string fortunesView = FortunesView.Render(fortunes); + byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView); + + return byteArray.ToArray(); + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/FortunesView.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs similarity index 54% rename from frameworks/CSharp/appmpower/src/FortunesView.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs index 8f56ddde4d5..2c11f6473c6 100644 --- a/frameworks/CSharp/appmpower/src/FortunesView.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/FortunesView.cs @@ -1,33 +1,23 @@ using System.Collections.Generic; -using System.IO.Pipelines; using System.Globalization; using System.Text; using System.Threading.Tasks; using System.Web; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Primitives; using PlatformBenchmarks; +using appMpower.Orm.Objects; -namespace appMpower +namespace appMpower.Orm { public static class FortunesView { - private readonly static KeyValuePair _headerServer = - new KeyValuePair("Server", "k"); - private readonly static KeyValuePair _headerContentType = - new KeyValuePair("Content-Type", "text/html; charset=UTF-8"); - public static char[] _fortunesTableStart = "Fortunes".ToCharArray(); public static char[] _fortunesRowStart = "".ToCharArray(); public static char[] _fortunesTableEnd = "
idmessage
".ToCharArray(); public static char[] _fortunesColumn = "".ToCharArray(); public static char[] _fortunesRowEnd = "
".ToCharArray(); - public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter pipeWriter, List fortunes) + public static string Render(List fortunes) { - headerDictionary.Add(_headerServer); - headerDictionary.Add(_headerContentType); - var writer = StringBuilderCache.Acquire(); writer.Append(_fortunesTableStart); @@ -39,10 +29,7 @@ public static async Task Render(IHeaderDictionary headerDictionary, PipeWriter p writer.Append(_fortunesTableEnd); - headerDictionary.Add(new KeyValuePair("Content-Length", (writer.Length + 32).ToString())); - - await pipeWriter.WriteAsync(Encoding.UTF8.GetBytes(StringBuilderCache.GetStringAndRelease(writer))); - pipeWriter.Complete(); + return StringBuilderCache.GetStringAndRelease(writer); } } } \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs similarity index 54% rename from frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs index 0f3e501c485..a5887f50142 100644 --- a/frameworks/CSharp/appmpower/src/Microsoft/BatchUpdateString.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/BatchUpdateString.cs @@ -1,7 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System.Linq; +using appMpower.Orm; +using appMpower.Orm.Data; namespace PlatformBenchmarks { @@ -33,51 +34,32 @@ public static string Query(int batchSize) //sb.Append("(?::int,?::int)) AS temp(id, randomNumber) WHERE temp.id = world.id"); */ -#if MYSQL - for (int i = 0; i < batchSize; i++) + if (Constants.Dbms == Dbms.MySQL) { - sb.Append("UPDATE world SET randomNumber=? WHERE id=?;"); + for (int i = 0; i < batchSize; i++) + { + sb.Append("UPDATE world SET randomNumber=? WHERE id=?;"); + } } -#elif ADO - /* - sb.Append("UPDATE world SET randomNumber = temp.randomNumber FROM (VALUES "); - Enumerable.Range(0, lastIndex).ToList().ForEach(i => sb.Append($"(@i{i}, @r{i}), ")); - sb.Append($"(@i{lastIndex}, @r{lastIndex}) ORDER BY 1) AS temp(id, randomNumber) WHERE temp.id = world.id"); - */ - - sb.Append("UPDATE world SET randomNumber=CASE id "); - - for (int i = 0; i < batchSize; i++) - { - sb.Append("WHEN @i" + i + " THEN @r" + i + " "); - } - - sb.Append("ELSE randomnumber END WHERE id IN("); - - for (int i = 0; i < lastIndex; i++) + else { - sb.Append("@j" + i + ","); - } + sb.Append("UPDATE world SET randomNumber=CASE id "); - sb.Append("@j" + lastIndex + ")"); -#else - sb.Append("UPDATE world SET randomNumber=CASE id "); + for (int i = 0; i < batchSize; i++) + { + sb.Append("WHEN ? THEN ? "); + } - for (int i = 0; i < batchSize; i++) - { - sb.Append("WHEN ? THEN ? "); - } + sb.Append("ELSE randomnumber END WHERE id IN("); - sb.Append("ELSE randomnumber END WHERE id IN("); + for (int i = 0; i < lastIndex; i++) + { + sb.Append("?,"); + } - for (int i = 0; i < lastIndex; i++) - { - sb.Append("?,"); + sb.Append("?)"); } - sb.Append("?)"); -#endif - return _queries[batchSize] = StringBuilderCache.GetStringAndRelease(sb); } } diff --git a/frameworks/CSharp/appmpower/src/Microsoft/ConcurrentRandom.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs similarity index 95% rename from frameworks/CSharp/appmpower/src/Microsoft/ConcurrentRandom.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs index b5a74d48884..374c9f4e1bb 100644 --- a/frameworks/CSharp/appmpower/src/Microsoft/ConcurrentRandom.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/ConcurrentRandom.cs @@ -1,9 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Runtime.CompilerServices; -using System.Threading; namespace PlatformBenchmarks { diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs new file mode 100644 index 00000000000..73b890db750 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Microsoft/StringBuilderCache.cs @@ -0,0 +1,54 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text; + +namespace PlatformBenchmarks; + +internal static class StringBuilderCache +{ + private const int DefaultCapacity = 1386; + private const int MaxBuilderSize = DefaultCapacity * 3; + [ThreadStatic] + private static StringBuilder t_cachedInstance; + + public static StringBuilder Acquire(int capacity = DefaultCapacity) + { + if (capacity <= MaxBuilderSize) + { + StringBuilder sb = t_cachedInstance; + + if (capacity < DefaultCapacity) + { + capacity = DefaultCapacity; + } + + if (sb != null) + { + if (capacity <= sb.Capacity) + { + t_cachedInstance = null; + sb.Clear(); + return sb; + } + } + } + + return new StringBuilder(capacity); + } + + public static void Release(StringBuilder sb) + { + if (sb.Capacity <= MaxBuilderSize) + { + t_cachedInstance = sb; + } + } + + public static string GetStringAndRelease(StringBuilder sb) + { + string result = sb.ToString(); + Release(sb); + return result; + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs new file mode 100644 index 00000000000..0f3ee5b59c2 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/NativeMethods.cs @@ -0,0 +1,144 @@ +using System.Runtime.InteropServices; +using System.Text; +using System.Text.Json; +using appMpower.Orm.Data; +using appMpower.Orm.Objects; +using appMpower.Orm.Serializers; + +namespace appMpower.Orm; + +public static class NativeMethods +{ + private static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions + { + Indented = false, + SkipValidation = true + }; + + private readonly static WorldSerializer _worldSerializer = new WorldSerializer(); + private readonly static WorldsSerializer _worldsSerializer = new WorldsSerializer(); + + [UnmanagedCallersOnly(EntryPoint = "Dbms")] + public static void Dbms(int dbms) + { + Constants.Dbms = (Dbms)dbms; + DbProviderFactory.SetConnectionString(); + } + + [UnmanagedCallersOnly(EntryPoint = "DbProvider")] + public static void DbProvider(int dbProvider) + { + Constants.DbProvider = (DbProvider)dbProvider; + DbProviderFactory.SetConnectionString(); + } + + [UnmanagedCallersOnly(EntryPoint = "FreeHandlePointer")] + public static void FreeHandlePointer(IntPtr handlePointer) + { + GCHandle handle = GCHandle.FromIntPtr(handlePointer); + handle.Free(); + } + + [UnmanagedCallersOnly(EntryPoint = "Db")] + public static unsafe IntPtr Db(int* length, IntPtr* handlePointer) + { + var world = RawDb.LoadSingleQueryRow(); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldSerializer.Serialize(utf8JsonWriter, world); + + *length = (int)utf8JsonWriter.BytesCommitted; + byte[] byteArray = memoryStream.ToArray(); + + GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); + // return the managed and byteArrayPointer pointer + IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + *handlePointer = GCHandle.ToIntPtr(handle); + + return byteArrayPointer; + /* + fixed(byte* b = memoryStream.ToArray()) + { + return b; + } + */ + } + + [UnmanagedCallersOnly(EntryPoint = "Fortunes")] + public static unsafe IntPtr Fortunes(int* length, IntPtr* handlePointer) + { + List fortunes = RawDb.LoadFortunesRows(); + string fortunesView = FortunesView.Render(fortunes); + byte[] byteArray = Encoding.UTF8.GetBytes(fortunesView); + + *length = byteArray.Length; + + GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); + IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + *handlePointer = GCHandle.ToIntPtr(handle); + + return byteArrayPointer; + } + + [UnmanagedCallersOnly(EntryPoint = "Query")] + public static unsafe IntPtr Query(int queries, int* length, IntPtr* handlePointer) + { + World[] worlds = RawDb.ReadMultipleRows(queries); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldsSerializer.Serialize(utf8JsonWriter, worlds); + + *length = (int)utf8JsonWriter.BytesCommitted; + byte[] byteArray = memoryStream.ToArray(); + + GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); + IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + *handlePointer = GCHandle.ToIntPtr(handle); + + return byteArrayPointer; + } + + [UnmanagedCallersOnly(EntryPoint = "Updates")] + public static unsafe IntPtr Updates(int count, int* length, IntPtr* handlePointer) + { + World[] worlds = RawDb.LoadMultipleUpdatesRows(count); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldsSerializer.Serialize(utf8JsonWriter, worlds); + + *length = (int)utf8JsonWriter.BytesCommitted; + byte[] byteArray = memoryStream.ToArray(); + + GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); + IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + *handlePointer = GCHandle.ToIntPtr(handle); + + return byteArrayPointer; + } + + [UnmanagedCallersOnly(EntryPoint = "DbById")] + public static unsafe IntPtr DbById(int id, int* length, IntPtr* handlePointer) + { + var world = RawDb.LoadSingleQueryRowById(id); + + var memoryStream = new MemoryStream(); + using var utf8JsonWriter = new Utf8JsonWriter(memoryStream, _jsonWriterOptions); + + _worldSerializer.Serialize(utf8JsonWriter, world); + + *length = (int)utf8JsonWriter.BytesCommitted; + byte[] byteArray = memoryStream.ToArray(); + + GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); + IntPtr byteArrayPointer = handle.AddrOfPinnedObject(); + *handlePointer = GCHandle.ToIntPtr(handle); + + return byteArrayPointer; + } +} diff --git a/frameworks/CSharp/appmpower/src/CachedWorld.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs similarity index 88% rename from frameworks/CSharp/appmpower/src/CachedWorld.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs index 857b8283c73..7ef3f074167 100644 --- a/frameworks/CSharp/appmpower/src/CachedWorld.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/CachedWorld.cs @@ -1,4 +1,4 @@ -namespace appMpower +namespace appMpower.Orm.Objects { public struct CachedWorld { diff --git a/frameworks/CSharp/appmpower/src/Fortune.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs similarity index 93% rename from frameworks/CSharp/appmpower/src/Fortune.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs index 4d1b99661ca..c6eb823c9fa 100644 --- a/frameworks/CSharp/appmpower/src/Fortune.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/Fortune.cs @@ -1,6 +1,4 @@ -using System; - -namespace appMpower +namespace appMpower.Orm.Objects { public readonly struct Fortune : IComparable, IComparable { diff --git a/frameworks/CSharp/appmpower/src/World.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs similarity index 78% rename from frameworks/CSharp/appmpower/src/World.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs index cfec08b1f9c..4e10e128998 100644 --- a/frameworks/CSharp/appmpower/src/World.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Objects/World.cs @@ -1,4 +1,4 @@ -namespace appMpower +namespace appMpower.Orm.Objects { public struct World { diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs new file mode 100644 index 00000000000..b748d78a251 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/RawDb.cs @@ -0,0 +1,257 @@ +using System.Data; +using appMpower.Orm.Data; +using appMpower.Orm.Objects; +using PlatformBenchmarks; + +namespace appMpower.Orm +{ + public static class RawDb + { + private const int MaxBatch = 500; + + private static Random _random = new Random(); + + private static string[] _queriesMultipleRows = new string[MaxBatch + 1]; + + public static World LoadSingleQueryRow() + { + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + var (dbCommand, _) = CreateReadCommand(pooledConnection); + + using (dbCommand) + { + World world = ReadSingleRow(dbCommand); + + return world; + } + } + + public static World LoadSingleQueryRowById(int id) + { + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + var (dbCommand, _) = CreateReadCommandById(pooledConnection, id); + + using (dbCommand) + { + World world = ReadSingleRow(dbCommand); + + return world; + } + } + + public static World[] LoadMultipleQueriesRows(int count) + { + var worlds = new World[count]; + + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + var (dbCommand, dbDataParameter) = CreateReadCommand(pooledConnection); + + using (dbCommand) + { + for (int i = 0; i < count; i++) + { + worlds[i] = ReadSingleRow(dbCommand); + dbDataParameter.Value = _random.Next(1, 10001); + } + } + + return worlds; + } + + public static List LoadFortunesRows() + { + var fortunes = new List(); + + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + var dbCommand = new DbCommand("SELECT * FROM fortune", pooledConnection); + + using (dbCommand) + { + IDataReader dataReader = dbCommand.ExecuteReader(CommandBehavior.SingleResult & CommandBehavior.SequentialAccess); + + while (dataReader.Read()) + { + fortunes.Add(new Fortune + ( + id: dataReader.GetInt32(0), + //MariaDB ODBC connector does not correctly support Japanese characters in combination with default ADO.NET; + //as a solution we custom read this string + message: (Constants.Dbms == Dbms.MySQL ? ReadColumn(dataReader, 1) : dataReader.GetString(1)) + )); + } + + dataReader.Close(); + } + + fortunes.Add(new Fortune(id: 0, message: "Additional fortune added at request time.")); + fortunes.Sort(); + + return fortunes; + } + + public static World[] LoadMultipleUpdatesRows(int count) + { + var worlds = new World[count]; + + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + var (queryCommand, dbDataParameter) = CreateReadCommand(pooledConnection, true); + + using (queryCommand) + { + for (int i = 0; i < count; i++) + { + worlds[i] = ReadSingleRow(queryCommand); + dbDataParameter.Value = _random.Next(1, 10001); + } + } + + using var updateCommand = new DbCommand(BatchUpdateString.Query(count), pooledConnection, true); + + var ids = BatchUpdateString.Ids; + var randoms = BatchUpdateString.Randoms; + + for (int i = 0; i < count; i++) + { + var randomNumber = _random.Next(1, 10001); + + updateCommand.CreateParameter(ids[i], DbType.Int32, worlds[i].Id); + updateCommand.CreateParameter(randoms[i], DbType.Int32, randomNumber); + + worlds[i].RandomNumber = randomNumber; + } + + if (Constants.Dbms != Dbms.MySQL) + { + var jds = BatchUpdateString.Jds; + + for (int i = 0; i < count; i++) + { + updateCommand.CreateParameter(jds[i], DbType.Int32, worlds[i].Id); + } + } + + updateCommand.ExecuteNonQuery(); + + return worlds; + } + + internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection) + { + DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection); + + return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001))); + } + + internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommand(DbConnection pooledConnection, bool keyed) + { + DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection, keyed); + + return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, _random.Next(1, 10001))); + } + + internal static (DbCommand dbCommand, IDbDataParameter dbDataParameter) CreateReadCommandById(DbConnection pooledConnection, int id) + { + DbCommand dbCommand = new DbCommand("SELECT * FROM world WHERE id=?", pooledConnection); + + return (dbCommand, dbCommand.CreateParameter("Id", DbType.Int32, id)); + } + + internal static World ReadSingleRow(DbCommand dbCommand) + { + var dataReader = dbCommand.ExecuteReader(CommandBehavior.SingleRow & CommandBehavior.SequentialAccess); + + dataReader.Read(); + + var world = new World + { + Id = dataReader.GetInt32(0), + RandomNumber = dataReader.GetInt32(1) + }; + + dataReader.Close(); + + return world; + } + + public static World[] ReadMultipleRows(int count) + { + int j = 0; + var ids = BatchUpdateString.Ids; + var worlds = new World[count]; + string queryString; + + if (_queriesMultipleRows[count] != null) + { + queryString = _queriesMultipleRows[count]; + } + else + { + var stringBuilder = StringBuilderCache.Acquire(); + + for (int i = 0; i < count; i++) + { + stringBuilder.Append("SELECT * FROM world WHERE id=?;"); + } + + queryString = _queriesMultipleRows[count] = StringBuilderCache.GetStringAndRelease(stringBuilder); + } + + using var pooledConnection = DbConnections.GetConnection(DbProviderFactory.ConnectionString); + pooledConnection.Open(); + + using var dbCommand = new DbCommand(queryString, pooledConnection); + + for (int i = 0; i < count; i++) + { + dbCommand.CreateParameter(ids[i], DbType.Int32, _random.Next(1, 10001)); + } + + var dataReader = dbCommand.ExecuteReader(CommandBehavior.Default & CommandBehavior.SequentialAccess); + + do + { + dataReader.Read(); + + worlds[j] = new World + { + Id = dataReader.GetInt32(0), + RandomNumber = dataReader.GetInt32(1) + }; + + j++; + } while (dataReader.NextResult()); + + dataReader.Close(); + + return worlds; + } + + public static string ReadColumn(IDataReader dataReader, int column) + { + long size = dataReader.GetBytes(column, 0, null, 0, 0); //get the length of data + byte[] values = new byte[size]; + + int bufferSize = 64; + long bytesRead = 0; + int currentPosition = 0; + + while (bytesRead < size) + { + bytesRead += dataReader.GetBytes(column, currentPosition, values, currentPosition, bufferSize); + currentPosition += bufferSize; + } + + return System.Text.Encoding.Default.GetString(values); + } + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs new file mode 100644 index 00000000000..8986ee387ee --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/IJsonSerializer.cs @@ -0,0 +1,9 @@ +using System.Text.Json; + +namespace appMpower.Orm.Serializers +{ + public interface IJsonSerializer + { + public void Serialize(Utf8JsonWriter utf8JsonWriter, T t); + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/WorldSerializer.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldSerializer.cs similarity index 68% rename from frameworks/CSharp/appmpower/src/WorldSerializer.cs rename to frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldSerializer.cs index 6150c5560b7..1e078da5957 100644 --- a/frameworks/CSharp/appmpower/src/WorldSerializer.cs +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldSerializer.cs @@ -1,8 +1,9 @@ using System.Text.Json; +using appMpower.Orm.Objects; -namespace appMpower +namespace appMpower.Orm.Serializers { - public class WorldSerializer : Kestrel.IJsonSerializer + public class WorldSerializer : IJsonSerializer { public void Serialize(Utf8JsonWriter utf8JsonWriter, World world) { @@ -10,6 +11,7 @@ public void Serialize(Utf8JsonWriter utf8JsonWriter, World world) utf8JsonWriter.WriteNumber("id", world.Id); utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber); utf8JsonWriter.WriteEndObject(); + utf8JsonWriter.Flush(); } } } diff --git a/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs new file mode 100644 index 00000000000..223af9bd702 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/Serializers/WorldsSerizalizer.cs @@ -0,0 +1,24 @@ +using System.Text.Json; +using appMpower.Orm.Objects; + +namespace appMpower.Orm.Serializers +{ + public class WorldsSerializer : IJsonSerializer + { + public void Serialize(Utf8JsonWriter utf8JsonWriter, World[] worlds) + { + utf8JsonWriter.WriteStartArray(); + + foreach (World world in worlds) + { + utf8JsonWriter.WriteStartObject(); + utf8JsonWriter.WriteNumber("id", world.Id); + utf8JsonWriter.WriteNumber("randomNumber", world.RandomNumber); + utf8JsonWriter.WriteEndObject(); + } + + utf8JsonWriter.WriteEndArray(); + utf8JsonWriter.Flush(); + } + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower.csproj b/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj similarity index 52% rename from frameworks/CSharp/appmpower/src/appMpower.csproj rename to frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj index 579c54883b5..dd9c929f19f 100644 --- a/frameworks/CSharp/appmpower/src/appMpower.csproj +++ b/frameworks/CSharp/appmpower/src/appMpower.Orm/appMpower.Orm.csproj @@ -1,55 +1,42 @@ - - - - net8.0 - Exe - true - - - - - true - true - true - false - Speed - none - false - - - true - true - true - false - - - true - - true - - - - - true - - - true - false - false - - - - - - - - - - $(DefineConstants);POSTGRESQL - $(DefineConstants);ODBC - $(DefineConstants);ADO - - - \ No newline at end of file + + + + net8.0 + enable + + true + true + true + + linux-x64 + + + + + true + false + Size + none + false + + true + true + true + false + + true + + true + + true + + true + false + false + + + + + + + diff --git a/frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs b/frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs new file mode 100644 index 00000000000..ab1685ab8ad --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/JsonMessage.cs @@ -0,0 +1,7 @@ +namespace appMpower +{ + public struct JsonMessage + { + public string Message { get; set; } + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs new file mode 100644 index 00000000000..0719f19c5ad --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/CachingMiddelware.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public class CachingMiddleware +{ + private static readonly Dictionary _cache = new(); + private static readonly Random _random = new(); + + private static readonly byte[] _startBytes = Encoding.UTF8.GetBytes("["); + private static readonly byte[] _endBytes = Encoding.UTF8.GetBytes("]"); + private static readonly byte[] _comma = Encoding.UTF8.GetBytes(","); + + + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("application/json")); + + private readonly RequestDelegate _next; + + public CachingMiddleware(RequestDelegate next) + { + _next = next; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/cached-worlds", StringComparison.Ordinal)) + { + int payloadLength; + IntPtr handlePointer; + IntPtr bytePointer; + byte[] json; + + if (_cache.Count == 0) + { + for (int i = 1; i < 10001; i++) + { + bytePointer = NativeMethods.DbById(i, out payloadLength, out handlePointer); + json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + _cache.Add(i, json); + } + } + + var queryString = httpContext.Request.QueryString.ToString(); + int queries; + Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out queries); + queries = queries > 500 ? 500 : (queries > 0 ? queries : 1); + + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + int queriesLength = 0; + int[] keys = new int[queries]; + + for (int i = 0; i < queries; i++) + { + keys[i] = _random.Next(1, 10001); + + if (!_cache.TryGetValue(keys[i], out json)) + { + bytePointer = NativeMethods.DbById(keys[i], out payloadLength, out handlePointer); + json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + _cache.Add(keys[i], json); + } + + queriesLength += json.Length; + } + + byte[] result = new byte[_startBytes.Length + _endBytes.Length + (_comma.Length * queries - 1) + queriesLength]; + int position = 0; + + Buffer.BlockCopy(_startBytes, 0, result, position, _startBytes.Length); + position += _startBytes.Length; + + for (int i = 0; i < queries; i++) + { + json = _cache[keys[i]]; + Buffer.BlockCopy(json, 0, result, position, json.Length); + position += json.Length; + + if (i < queries - 1) + { + Buffer.BlockCopy(_comma, 0, result, position, _comma.Length); + position += _comma.Length; + } + } + + Buffer.BlockCopy(_endBytes, 0, result, position, _endBytes.Length); + + response.Headers.Add( + new KeyValuePair("Content-Length", result.Length.ToString())); + + return response.Body.WriteAsync(result, 0, result.Length); + } + + return _next(httpContext); + } +} + +public static class CachingMiddlewareExtensions +{ + public static IApplicationBuilder UseCaching(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs new file mode 100644 index 00000000000..2acf9af1716 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/FortunesMiddleware.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public class FortunesMiddleware +{ + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("text/html; charset=UTF-8")); + + private readonly RequestDelegate _next; + + public FortunesMiddleware(RequestDelegate next) + { + _next = next; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/fortunes", StringComparison.Ordinal)) + { + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + int payloadLength; + IntPtr handlePointer; + + IntPtr bytePointer = NativeMethods.Fortunes(out payloadLength, out handlePointer); + byte[] json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + + response.Headers.Add( + new KeyValuePair("Content-Length", payloadLength.ToString())); + + return response.Body.WriteAsync(json, 0, payloadLength); + } + + return _next(httpContext); + } +} + +public static class FortunesMiddlewareExtensions +{ + public static IApplicationBuilder UseFortunes(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs new file mode 100644 index 00000000000..2e90051ff2f --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/JsonMiddleware.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; +using appMpower.Serializers; + +namespace appMpower; + +public class JsonMiddleware +{ + private readonly static JsonWriterOptions _jsonWriterOptions = new JsonWriterOptions + { + Indented = false, + SkipValidation = true + }; + + private readonly static JsonMessageSerializer _jsonMessageSerializer = new JsonMessageSerializer(); + + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("application/json")); + + private readonly RequestDelegate _nextStage; + + public JsonMiddleware(RequestDelegate nextStage) + { + _nextStage = nextStage; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/json", StringComparison.Ordinal)) + { + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + using var utf8JsonWriter = new Utf8JsonWriter(httpContext.Response.Body, _jsonWriterOptions); + + _jsonMessageSerializer.Serialize(utf8JsonWriter, new JsonMessage { Message = "Hello, World!" }); + + response.Headers.Add( + new KeyValuePair("Content-Length", utf8JsonWriter.BytesPending.ToString())); + + utf8JsonWriter.Flush(); + + return Task.CompletedTask; + } + + return _nextStage(httpContext); + } +} + +public static class JsonMiddlewareExtensions +{ + public static IApplicationBuilder UseJson(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs new file mode 100644 index 00000000000..63964f0b90c --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleQueriesMiddleware.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public class MultipleQueriesMiddleware +{ + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("application/json")); + + private readonly RequestDelegate _next; + + public MultipleQueriesMiddleware(RequestDelegate next) + { + _next = next; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/queries", StringComparison.Ordinal)) + { + var queryString = httpContext.Request.QueryString.ToString(); + int queries; + Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out queries); + queries = queries > 500 ? 500 : (queries > 0 ? queries : 1); + + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + int payloadLength; + IntPtr handlePointer; + + IntPtr bytePointer = NativeMethods.Query(queries, out payloadLength, out handlePointer); + byte[] json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + + response.Headers.Add( + new KeyValuePair("Content-Length", payloadLength.ToString())); + + return response.Body.WriteAsync(json, 0, payloadLength); + } + + return _next(httpContext); + } +} + +public static class MultipleQueriesMiddlewareExtensions +{ + public static IApplicationBuilder UseMultipleQueries(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs new file mode 100644 index 00000000000..5308afd3811 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/MultipleUpdatesMiddleware.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public class MultipleUpdatesMiddelware +{ + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("application/json")); + + private readonly RequestDelegate _next; + + public MultipleUpdatesMiddelware(RequestDelegate next) + { + _next = next; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/updates", StringComparison.Ordinal)) + { + var queryString = httpContext.Request.QueryString.ToString(); + int count; + Int32.TryParse(queryString.Substring(queryString.LastIndexOf("=") + 1), out count); + count = count > 500 ? 500 : (count > 0 ? count : 1); + + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + int payloadLength; + IntPtr handlePointer; + + IntPtr bytePointer = NativeMethods.Updates(count, out payloadLength, out handlePointer); + byte[] json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + + response.Headers.Add( + new KeyValuePair("Content-Length", payloadLength.ToString())); + + return response.Body.WriteAsync(json, 0, payloadLength); + } + + return _next(httpContext); + } +} + +public static class MultipleUpdatesMiddelwareExtensions +{ + public static IApplicationBuilder UseMultipleUpdates(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs new file mode 100644 index 00000000000..cf7ad20e54a --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/PlaintextMiddleware.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public unsafe class PlaintextMiddleware +{ + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("text/plain")); + private static readonly byte[] _helloWorldPayload = Encoding.UTF8.GetBytes("Hello, World!"); + + private readonly RequestDelegate _nextStage; + + public PlaintextMiddleware(RequestDelegate nextStage) + { + _nextStage = nextStage; + } + + public Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/plaintext", StringComparison.Ordinal)) + { + var payloadLength = _helloWorldPayload.Length; + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + response.Headers.Add( + new KeyValuePair("Content-Length", payloadLength.ToString())); + + return response.Body.WriteAsync(_helloWorldPayload, 0, payloadLength); + } + + return _nextStage(httpContext); + } +} + +public static class PlaintextMiddlewareExtensions +{ + public static IApplicationBuilder UsePlainText(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs b/frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs new file mode 100644 index 00000000000..d43de484b66 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Middleware/SingleQueryMiddleware.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Primitives; + +namespace appMpower; + +public class SingleQueryMiddleware +{ + private readonly static KeyValuePair _headerServer = + new KeyValuePair("Server", new StringValues("k")); + private readonly static KeyValuePair _headerContentType = + new KeyValuePair("Content-Type", new StringValues("application/json")); + + private readonly RequestDelegate _nextStage; + + public SingleQueryMiddleware(RequestDelegate nextStage) + { + _nextStage = nextStage; + } + + public unsafe Task Invoke(HttpContext httpContext) + { + if (httpContext.Request.Path.StartsWithSegments("/db", StringComparison.Ordinal)) + { + var response = httpContext.Response; + response.Headers.Add(_headerServer); + response.Headers.Add(_headerContentType); + + int payloadLength; + IntPtr handlePointer; + + IntPtr bytePointer = NativeMethods.Db(out payloadLength, out handlePointer); + byte[] json = new byte[payloadLength]; + Marshal.Copy(bytePointer, json, 0, payloadLength); + NativeMethods.FreeHandlePointer(handlePointer); + + response.Headers.Add( + new KeyValuePair("Content-Length", payloadLength.ToString())); + + return response.Body.WriteAsync(json, 0, payloadLength); + } + + return _nextStage(httpContext); + } +} + +public static class SingleQueryMiddlewareExtensions +{ + public static IApplicationBuilder UseSingleQuery(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs b/frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs new file mode 100644 index 00000000000..e24104d47fe --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/NativeMethods.cs @@ -0,0 +1,62 @@ +using System; +using System.Runtime.InteropServices; + +public unsafe partial class NativeMethods +{ +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern void Dbms(int dbms); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern void DbProvider(int dbProvider); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl)] +#endif + public static extern void FreeHandlePointer(IntPtr handlePointer); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + //public static extern byte* Db(out int length); + public static extern IntPtr Db(out int length, out IntPtr handlePointer); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern IntPtr Fortunes(out int length, out IntPtr handlePointer); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern IntPtr Query(int queries, out int length, out IntPtr handlePointer); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern IntPtr Updates(int queries, out int length, out IntPtr handlePointer); + +#if DEBUG + [DllImport("appMpower.Orm.dylib", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#else + [DllImport("appMpower.Orm.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)] +#endif + public static extern IntPtr DbById(int id, out int length, out IntPtr handlePointer); +} diff --git a/frameworks/CSharp/appmpower/src/appMpower/Program.cs b/frameworks/CSharp/appmpower/src/appMpower/Program.cs new file mode 100644 index 00000000000..f2f36aa627d --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Program.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; + +namespace appMpower; + +class Program +{ + static void Main(string[] args) + { + BuildWebHost(args).Run(); + } + + static IHost BuildWebHost(string[] args) + { + var config = new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddEnvironmentVariables(prefix: "ASPNETCORE_") + .AddCommandLine(args) + .Build(); + + var appSettings = config.GetSection("AppSettings").Get(); + + var host = Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseConfiguration(config) + .UseKestrel(options => + { + options.AddServerHeader = false; + options.AllowSynchronousIO = true; + }) + .UseStartup(); + }) + .Build(); + + return host; + } +} + +public class AppSettings +{ + public string Database { get; set; } +} diff --git a/frameworks/CSharp/appmpower/src/Kestrel/IJsonSerializer.cs b/frameworks/CSharp/appmpower/src/appMpower/Serializers/IJsonSerializer.cs similarity index 81% rename from frameworks/CSharp/appmpower/src/Kestrel/IJsonSerializer.cs rename to frameworks/CSharp/appmpower/src/appMpower/Serializers/IJsonSerializer.cs index 4f28a4cc538..eb59ff827ed 100644 --- a/frameworks/CSharp/appmpower/src/Kestrel/IJsonSerializer.cs +++ b/frameworks/CSharp/appmpower/src/appMpower/Serializers/IJsonSerializer.cs @@ -1,6 +1,6 @@ using System.Text.Json; -namespace appMpower.Kestrel +namespace appMpower.Serializers { public interface IJsonSerializer { diff --git a/frameworks/CSharp/appmpower/src/JsonMessageSerializer.cs b/frameworks/CSharp/appmpower/src/appMpower/Serializers/JsonMessageSerializer.cs similarity index 58% rename from frameworks/CSharp/appmpower/src/JsonMessageSerializer.cs rename to frameworks/CSharp/appmpower/src/appMpower/Serializers/JsonMessageSerializer.cs index dca7f673368..c06636f1a31 100644 --- a/frameworks/CSharp/appmpower/src/JsonMessageSerializer.cs +++ b/frameworks/CSharp/appmpower/src/appMpower/Serializers/JsonMessageSerializer.cs @@ -1,13 +1,13 @@ using System.Text.Json; -namespace appMpower +namespace appMpower.Serializers { - public class JsonMessageSerializer : Kestrel.IJsonSerializer + public class JsonMessageSerializer : IJsonSerializer { public void Serialize(Utf8JsonWriter utf8JsonWriter, JsonMessage jsonMessage) { utf8JsonWriter.WriteStartObject(); - utf8JsonWriter.WriteString("message", jsonMessage.message); + utf8JsonWriter.WriteString("message", jsonMessage.Message); utf8JsonWriter.WriteEndObject(); } } diff --git a/frameworks/CSharp/appmpower/src/appMpower/Startup.cs b/frameworks/CSharp/appmpower/src/appMpower/Startup.cs new file mode 100644 index 00000000000..4b571cf8286 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/Startup.cs @@ -0,0 +1,56 @@ +using System.Text.Encodings.Web; +using System.Text.Unicode; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace appMpower; + +public class Startup +{ + private readonly IConfiguration _configuration; + + public Startup(IConfiguration configuration) + { + _configuration = configuration; + } + + public void ConfigureServices(IServiceCollection services) + { + var appSettings = _configuration.Get(); + services.AddSingleton(appSettings); + +#if !DEBUG + #if ODBC + NativeMethods.DbProvider(1); //ODBC + #else + NativeMethods.DbProvider(0); //ADO + #endif + + #if POSTGRESQL + NativeMethods.Dbms(1); //PostgreSQL + #else + NativeMethods.Dbms(0); //MySQL + #endif +#endif + + var settings = new TextEncoderSettings(UnicodeRanges.BasicLatin, UnicodeRanges.Katakana, UnicodeRanges.Hiragana); + + settings.AllowCharacter('—'); + services.AddWebEncoders(options => + { + options.TextEncoderSettings = settings; + }); + } + + public void Configure(IApplicationBuilder app) + { + app.UsePlainText(); + app.UseJson(); + app.UseSingleQuery(); + app.UseCaching(); + app.UseFortunes(); + app.UseMultipleQueries(); + app.UseMultipleUpdates(); + } +} \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj b/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj new file mode 100644 index 00000000000..5661d01ce61 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/appMpower.csproj @@ -0,0 +1,35 @@ + + + + net8.0 + Exe + true + + + + + + + + + + + + + + + + $(DefineConstants);ODBC + $(DefineConstants);POSTGRESQL + $(DefineConstants);MYSQL + + + \ No newline at end of file diff --git a/frameworks/CSharp/appmpower/src/appMpower/appsettings.json b/frameworks/CSharp/appmpower/src/appMpower/appsettings.json new file mode 100644 index 00000000000..0b1badf0626 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/appMpower/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "None", + "Microsoft": "None", + "Microsoft.Hosting.Lifetime": "None" + } + } +} diff --git a/frameworks/CSharp/appmpower/src/nuget.config b/frameworks/CSharp/appmpower/src/appMpower/nuget.config similarity index 100% rename from frameworks/CSharp/appmpower/src/nuget.config rename to frameworks/CSharp/appmpower/src/appMpower/nuget.config diff --git a/frameworks/CSharp/appmpower/src/src.sln b/frameworks/CSharp/appmpower/src/src.sln new file mode 100644 index 00000000000..bedda48f506 --- /dev/null +++ b/frameworks/CSharp/appmpower/src/src.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "appMpower.Orm", "appMpower.Orm\appMpower.Orm.csproj", "{1EC05247-7299-4F69-887B-3B746DF5F878}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "appMpower", "appMpower\appMpower.csproj", "{EB5D3496-53B9-49A7-A3AD-754078142F81}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1EC05247-7299-4F69-887B-3B746DF5F878}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1EC05247-7299-4F69-887B-3B746DF5F878}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1EC05247-7299-4F69-887B-3B746DF5F878}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1EC05247-7299-4F69-887B-3B746DF5F878}.Release|Any CPU.Build.0 = Release|Any CPU + {EB5D3496-53B9-49A7-A3AD-754078142F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EB5D3496-53B9-49A7-A3AD-754078142F81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EB5D3496-53B9-49A7-A3AD-754078142F81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EB5D3496-53B9-49A7-A3AD-754078142F81}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal From 2fa6c6512603b8852703c30a51b2c90e57eeef84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 20:50:23 +0000 Subject: [PATCH 03/40] Bump rexml from 3.3.3 to 3.3.6 in /frameworks/Ruby/rack Bumps [rexml](https://github.com/ruby/rexml) from 3.3.3 to 3.3.6. - [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.3...v3.3.6) --- 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 7a08fdf7195..f3224c850b1 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.3) + rexml (3.3.6) strscan rubocop (1.64.1) json (~> 2.3) From 19580460e86ab14aba9f40f65aeede53ff8b159b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:07:31 +0000 Subject: [PATCH 04/40] Bump diesel from 1.4.6 to 2.2.3 in /frameworks/Rust/tide Bumps [diesel](https://github.com/diesel-rs/diesel) from 1.4.6 to 2.2.3. - [Release notes](https://github.com/diesel-rs/diesel/releases) - [Changelog](https://github.com/diesel-rs/diesel/blob/v2.2.3/CHANGELOG.md) - [Commits](https://github.com/diesel-rs/diesel/compare/v1.4.6...v2.2.3) --- updated-dependencies: - dependency-name: diesel dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Rust/tide/Cargo.lock | 178 ++++++++++++++++++++++++++------ frameworks/Rust/tide/Cargo.toml | 2 +- 2 files changed, 150 insertions(+), 30 deletions(-) diff --git a/frameworks/Rust/tide/Cargo.lock b/frameworks/Rust/tide/Cargo.lock index e9aa1d8598d..7ed70839854 100644 --- a/frameworks/Rust/tide/Cargo.lock +++ b/frameworks/Rust/tide/Cargo.lock @@ -93,7 +93,7 @@ checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522" dependencies = [ "askama_shared", "proc-macro2", - "syn", + "syn 1.0.60", ] [[package]] @@ -116,7 +116,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn", + "syn 1.0.60", "toml", ] @@ -127,7 +127,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -331,7 +331,7 @@ checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -380,6 +380,12 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "bitvec" version = "0.19.4" @@ -609,7 +615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" dependencies = [ "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -621,6 +627,41 @@ dependencies = [ "cipher", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.75", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.75", +] + [[package]] name = "dashmap" version = "4.0.2" @@ -639,26 +680,38 @@ checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" [[package]] name = "diesel" -version = "1.4.6" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542" +checksum = "65e13bab2796f412722112327f3e575601a3e9cdcbe426f0d30dbf43f3f5dc71" dependencies = [ - "bitflags", + "bitflags 2.6.0", "byteorder", "diesel_derives", + "itoa 1.0.11", "pq-sys", "r2d2", ] [[package]] name = "diesel_derives" -version = "1.4.1" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4" dependencies = [ + "diesel_table_macro_syntax", + "dsl_auto_type", "proc-macro2", "quote", - "syn", + "syn 2.0.75", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25" +dependencies = [ + "syn 2.0.75", ] [[package]] @@ -676,6 +729,26 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" +[[package]] +name = "dsl_auto_type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5d9abe6314103864cc2d8901b7ae224e0ab1a103a0a416661b4097b0779b607" +dependencies = [ + "darling", + "either", + "heck", + "proc-macro2", + "quote", + "syn 2.0.75", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "event-listener" version = "2.5.1" @@ -707,6 +780,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -768,7 +847,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -837,6 +916,12 @@ dependencies = [ "web-sys", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -923,6 +1008,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6cab2627acfc432780848602f3f558f7e9dd427352224b0d9324025796d2a5e" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.2.2" @@ -955,6 +1046,12 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "js-sys" version = "0.3.48" @@ -986,7 +1083,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.2.1", "cfg-if 1.0.0", "ryu", "static_assertions", @@ -1153,7 +1250,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -1227,18 +1324,18 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "quote" -version = "1.0.9" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1317,7 +1414,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" dependencies = [ - "bitflags", + "bitflags 1.2.1", ] [[package]] @@ -1388,7 +1485,7 @@ checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -1397,7 +1494,7 @@ version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43535db9747a4ba938c0ce0a98cc631a46ebf943c9e1d604e091df6007620bf6" dependencies = [ - "itoa", + "itoa 0.4.7", "ryu", "serde", ] @@ -1421,7 +1518,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.7", "ryu", "serde", ] @@ -1541,7 +1638,7 @@ dependencies = [ "quote", "serde", "serde_derive", - "syn", + "syn 1.0.60", ] [[package]] @@ -1557,7 +1654,7 @@ dependencies = [ "serde_derive", "serde_json", "sha1", - "syn", + "syn 1.0.60", ] [[package]] @@ -1566,6 +1663,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.4.0" @@ -1589,6 +1692,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tap" version = "1.0.1" @@ -1612,7 +1726,7 @@ checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.60", ] [[package]] @@ -1697,7 +1811,7 @@ dependencies = [ "proc-macro2", "quote", "standback", - "syn", + "syn 1.0.60", ] [[package]] @@ -1739,6 +1853,12 @@ dependencies = [ "matches", ] +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + [[package]] name = "unicode-normalization" version = "0.1.17" @@ -1840,7 +1960,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn", + "syn 1.0.60", "wasm-bindgen-shared", ] @@ -1874,7 +1994,7 @@ checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/frameworks/Rust/tide/Cargo.toml b/frameworks/Rust/tide/Cargo.toml index 80c05675a77..18b2aeea38c 100644 --- a/frameworks/Rust/tide/Cargo.toml +++ b/frameworks/Rust/tide/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" askama = "0.10.5" async-std = { version = "1.9.0", features = ["attributes"] } async-trait = "0.1.42" -diesel = { version = "1.4.6", features = ["postgres", "r2d2"] } +diesel = { version = "2.2.3", features = ["postgres", "r2d2"] } http-types = "2.10.0" rand = { version = "0.7", features = ["small_rng"] } serde = { version = "1.0.123", features = ["derive"] } From 0ffacd956b5354a9c5848e61e0d2ea85af262c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=81=D1=82=D1=8F=20=D0=A2=D1=80=D0=B5=D1=82?= =?UTF-8?q?=D1=8F=D0=BA?= Date: Mon, 26 Aug 2024 19:12:32 +0300 Subject: [PATCH 05/40] refactor(ditsmod): upgrade Ditsmod, removed bun specific TypeScript code (#9216) * chore(ditsmod): upgrade Ditsmod, removed bun.lockb and bun-providers.ts. * refactor(ditsmod): removed bun specific TypeScript code. * refactor(ditsmod): significantly simplifying the structure of the app and reducing the number of tests. --- frameworks/TypeScript/ditsmod/.gitignore | 1 + .../TypeScript/ditsmod/benchmark_config.json | 149 ++---------------- frameworks/TypeScript/ditsmod/bun.lockb | Bin 59387 -> 0 bytes .../ditsmod/ditsmod-bun-mysql.dockerfile | 3 +- .../ditsmod/ditsmod-bun-postgres.dockerfile | 3 +- .../TypeScript/ditsmod/ditsmod-bun.dockerfile | 3 +- frameworks/TypeScript/ditsmod/package.json | 7 +- .../TypeScript/ditsmod/src/app/app.module.ts | 19 ++- .../app/bun-integration/bun-application.ts | 17 -- .../src/app/bun-integration/bun-providers.ts | 21 --- .../src/app/bun-integration/node-res.ts | 61 ------- .../src/app/bun-integration/pre-router.ts | 26 --- .../ditsmod/src/app/bun-integration/spawn.ts | 9 -- .../{modules/service/db => }/db.service.ts | 2 +- .../ditsmod/src/app/{utils => }/helper.ts | 2 +- .../service/db => }/init.extension.ts | 0 .../modules/routed/simple/db.controller.ts | 39 ----- .../modules/routed/simple/db.controller2.ts | 40 ----- .../routed/simple/fortune.controller.ts | 41 ----- .../routed/simple/fortune.controller2.ts | 43 ----- .../modules/routed/simple/simple.module.ts | 23 --- .../routed/simple/singleton.controller.ts | 18 --- .../routed/simple/without-db.controller.ts | 18 --- .../src/app/modules/service/db/db.module.ts | 13 -- .../{modules/service/db => }/mysql.service.ts | 0 .../ditsmod/src/app/one.controller.ts | 88 +++++++++++ .../service/db => }/postgres.service.ts | 0 .../app/{modules/service/db => }/tokens.ts | 0 .../src/app/{modules/service/db => }/types.ts | 0 frameworks/TypeScript/ditsmod/src/main.bun.ts | 12 -- frameworks/TypeScript/ditsmod/tsconfig.json | 6 - 31 files changed, 116 insertions(+), 548 deletions(-) delete mode 100755 frameworks/TypeScript/ditsmod/bun.lockb delete mode 100644 frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-application.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-providers.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/bun-integration/node-res.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/bun-integration/pre-router.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/bun-integration/spawn.ts rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/db.service.ts (96%) rename frameworks/TypeScript/ditsmod/src/app/{utils => }/helper.ts (90%) rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/init.extension.ts (100%) delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller2.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller2.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/simple.module.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/singleton.controller.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/without-db.controller.ts delete mode 100644 frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.module.ts rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/mysql.service.ts (100%) create mode 100644 frameworks/TypeScript/ditsmod/src/app/one.controller.ts rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/postgres.service.ts (100%) rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/tokens.ts (100%) rename frameworks/TypeScript/ditsmod/src/app/{modules/service/db => }/types.ts (100%) delete mode 100644 frameworks/TypeScript/ditsmod/src/main.bun.ts diff --git a/frameworks/TypeScript/ditsmod/.gitignore b/frameworks/TypeScript/ditsmod/.gitignore index b7c122d83c3..d525fa34c07 100644 --- a/frameworks/TypeScript/ditsmod/.gitignore +++ b/frameworks/TypeScript/ditsmod/.gitignore @@ -5,3 +5,4 @@ dist* .pnp* nodemon.json package-lock.json +bun.lockb diff --git a/frameworks/TypeScript/ditsmod/benchmark_config.json b/frameworks/TypeScript/ditsmod/benchmark_config.json index c16c9419bde..11704b96a53 100755 --- a/frameworks/TypeScript/ditsmod/benchmark_config.json +++ b/frameworks/TypeScript/ditsmod/benchmark_config.json @@ -3,6 +3,7 @@ "tests": [ { "default": { + "dockerfile": "ditsmod.dockerfile", "json_url": "/json", "plaintext_url": "/plaintext", "port": 8080, @@ -17,31 +18,12 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "Ditsmod", - "notes": "", - "versus": "nodejs" - }, - "simplified-di": { - "dockerfile": "ditsmod.dockerfile", - "json_url": "/json2", - "plaintext_url": "/plaintext2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "None", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "None", - "platform": "nodejs", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod [simplified use of di]", + "display_name": "ditsmod", "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "nodejs" }, "postgres": { + "dockerfile": "ditsmod-postgres.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", @@ -60,10 +42,11 @@ "os": "Linux", "database_os": "Linux", "display_name": "ditsmod [postgres]", - "notes": "", + "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "nodejs" }, "mysql": { + "dockerfile": "ditsmod-mysql.dockerfile", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", @@ -82,52 +65,6 @@ "os": "Linux", "database_os": "Linux", "display_name": "ditsmod [mysql]", - "notes": "", - "versus": "nodejs" - }, - "postgres2": { - "dockerfile": "ditsmod-postgres.dockerfile", - "db_url": "/db2", - "query_url": "/queries2?queries=", - "update_url": "/updates2?queries=", - "cached_query_url": "/cached-queries2?count=", - "fortune_url": "/fortunes2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "Postgres", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "Raw", - "platform": "nodejs", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod [postgres & simplified use of di]", - "notes": "Simplified use of Dependency Injection (no request level injector).", - "versus": "nodejs" - }, - "mysql2": { - "dockerfile": "ditsmod-mysql.dockerfile", - "db_url": "/db2", - "query_url": "/queries2?queries=", - "update_url": "/updates2?queries=", - "cached_query_url": "/cached-queries2?count=", - "fortune_url": "/fortunes2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "MySQL", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "Raw", - "platform": "nodejs", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod [mysql & simplified use of di]", "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "nodejs" }, @@ -139,7 +76,7 @@ "approach": "Realistic", "classification": "Micro", "database": "None", - "framework": "Ditsmod", + "framework": "ditsmod-bun", "language": "TypeScript", "flavor": "None", "orm": "None", @@ -147,27 +84,7 @@ "webserver": "None", "os": "Linux", "database_os": "Linux", - "display_name": "Ditsmod on bun", - "notes": "", - "versus": "bun" - }, - "simplified-di-bun": { - "dockerfile": "ditsmod-bun.dockerfile", - "json_url": "/json2", - "plaintext_url": "/plaintext2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "None", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "None", - "platform": "bun", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod on bun [simplified use of di]", + "display_name": "ditsmod on bun", "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "bun" }, @@ -182,7 +99,7 @@ "approach": "Realistic", "classification": "Micro", "database": "Postgres", - "framework": "Ditsmod", + "framework": "ditsmod-bun", "language": "TypeScript", "flavor": "None", "orm": "Raw", @@ -191,7 +108,7 @@ "os": "Linux", "database_os": "Linux", "display_name": "ditsmod on bun [postgres]", - "notes": "", + "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "bun" }, "mysql-bun": { @@ -205,7 +122,7 @@ "approach": "Realistic", "classification": "Micro", "database": "MySQL", - "framework": "Ditsmod", + "framework": "ditsmod-bun", "language": "TypeScript", "flavor": "None", "orm": "Raw", @@ -214,52 +131,6 @@ "os": "Linux", "database_os": "Linux", "display_name": "ditsmod on bun [mysql]", - "notes": "", - "versus": "bun" - }, - "postgres2-bun": { - "dockerfile": "ditsmod-bun-postgres.dockerfile", - "db_url": "/db2", - "query_url": "/queries2?queries=", - "update_url": "/updates2?queries=", - "cached_query_url": "/cached-queries2?count=", - "fortune_url": "/fortunes2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "Postgres", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "Raw", - "platform": "bun", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod on bun [postgres & simplified use of di]", - "notes": "Simplified use of Dependency Injection (no request level injector).", - "versus": "bun" - }, - "mysql2-bun": { - "dockerfile": "ditsmod-bun-mysql.dockerfile", - "db_url": "/db2", - "query_url": "/queries2?queries=", - "update_url": "/updates2?queries=", - "cached_query_url": "/cached-queries2?count=", - "fortune_url": "/fortunes2", - "port": 8080, - "approach": "Realistic", - "classification": "Micro", - "database": "MySQL", - "framework": "Ditsmod", - "language": "TypeScript", - "flavor": "None", - "orm": "Raw", - "platform": "bun", - "webserver": "None", - "os": "Linux", - "database_os": "Linux", - "display_name": "ditsmod on bun [mysql & simplified use of di]", "notes": "Simplified use of Dependency Injection (no request level injector).", "versus": "bun" } diff --git a/frameworks/TypeScript/ditsmod/bun.lockb b/frameworks/TypeScript/ditsmod/bun.lockb deleted file mode 100755 index c15ebbf0d57fa7a70302adedf5ceb815a5c211fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59387 zcmeFa2{=|=`!;?XL*__G<}%L>LS&vvh7dB`xXU~wLW-nJnIcM3DKsjQN=nF3D)W@6 zl(|$S4gYI#@8{j``@PTe=zV|x@B5DLXdRs{dtd83*R`&-_Fik>Lxcrog98I(T}VE% zM4#OPF2Ozw0BJ8@*In);FQT-&Z-BRRko0aj21){fFzfUs|Ld;g>;&BuJ-(?W(`&9P zO$Z0lT>CLS{G=*0$9>mZs08KYf+5iTi;W^57v_+EnKz6CLX@9xV30=uG0@vNfaL7v zLdXOUJ)D=NAP^Y9R)IzJ+=xE@!9)Uq8~jV*I1Iu<=U0HA87#(21V7^CQ7!0%_y)Lz z1UUO0gJX0)k$m2phaI zc_aCF5(7vi{f1JGn2?t?N(0O7Yi~yYfPCj;a^$qZWxSV&+ zhfnBQP9X3=y&AA6Pv0TmD9^zGB!JP*-0!A|u3y&QF3LQWW(HEQ+IpY~3K~ zD6jTlQM*lW9_8ge*^&aK=Tm(Q8bkHU$mc^mNv@s{4=Iqi2PKvV1|PLE4i@##&pF6b z8j^hx>LXr0*^a^FK*w3+<9NP>JbDp#qwW#*!!h#vknJ9@C@wc5(NCHbNJt{{!okj; z_jL^lAo&o9fx$r}$e%mO$4xrekH9Uk&<|#^^+T7wa}bDl!F3TtU>02P69eJ03kW5+ zdOCaUg7zEWJj#=&bD%WL4Uc=|dZ|JS{Tcv^;&XtysC`J=e7;-7;x^xjPjSeOScp#;L@>IK~)u&AAYH4E*QgGI+K0nV;O z7-w0rh4aB+QQUQ4k>8sb;6YR%5U_D{BL&P4qo>tu)mG=)L z{7!Ttc-zC|Y(kZ!wlXYRYp|@({qQmu-n1 zlDkkhKBiB>e)v?<35&XooT+(pJ14g4+8xcT%(*~6MeU(G*=;$bL=(AMXz*-Rfm+Nd z(I_d&gG85JM>&fU$y-tGis)Op?n7)sBVhel0WO@70ypN=(uHK!q4{J1kH&T<6`xR;mll=ZF_9Cw3;|f z)ej^^6O;yc8fwqpc-U6jk*q%u*AsNjw1KXKo8RdEGT|jjr%SB9M>Jb0cwPV4(Cq0^ zC+-v#GT_cq_$AEibCQvhyG`N*kFBXrP2)&uq?55f&D)H1K3SI;*|JBtR`j=eaGsNT zFgp0O_2G%GCu_oY&po=Tc|2>6GsBN}LZ4=WIFEaauW~6$cQJdG*WY@%jKAofR8F^w z)e6JigN7|~ril(LB084p8B*IHGn%y8l}?HuS|Xlna;D_G3ctQ%SgN5>yj%LUJKgpD z#K_^00Na7{W|y9YjCXLaP3nqgnLTrnl9FYj&HBNM+81TTEUp&k^2WZn^f@h~Qz{nR zmjCtOPmxhZ0q&&-L={FXYU?|R1v_Ob%Vjhb#Gc=0SNZH@oZ48xrL%MSoj8T8bd86t z<=a+t%_O^3^GL5dz1OZ^Z1PT; zIb$}ZdqK*kdn@}$hX!YV*2a5u5e&mNeCl}#U!Mow`_X2hN^jLQAj!^e6vihsAY4T+ zbjyz7M33&wDL;YThF1eP46F9s`n;ZIqd~DEov4X{vHg(^$E4E*tJ&+X*Y8W!^tdQm z#r(EV@4DNEF5$zFeH>EAF&eGm3~@1u}9)1Z+O*1ALbzv zGf(N3K)vu~r(GNe&RcJ3G<9aZQP&}?y5wN!q1ew3<_X^e8zf}UZ>kzP=n~Pc`1u{v zbunV|tNn7u%eQyxRJ*!9Uh^>^t=F@HX2%1EqMzPttRU6BD2KtonGbty4t#QPYzV9&<;Tl$+JnBq8~@ zC8m2r{KO|T9}O#A48HneEO+-EY0`6=fZ09KA6|*(a&K~^ywf^K*G~cWz5k}bc5c4p z!OsnFABAliftn03e_JqqC)8X=<|B>8#)a{ffuI6>Si|PqM;ePM7(WR3s=!AaTEMUJ zn}DwYe58kB$8_P>zbsfiM)*Yu$Nx(b&WZ6g;FpcShdmQoFVUW5Q3d12!Y`YFPXjF2 z5)qJHOu_hdWIh9I3Q$2YET&+5I!HJgKiH%FQo;CJfRDxx%{|yc{qZF8cVZa7l-xcV zci7tg^7y?6BAWkb?0= zT4*258|6i{yif__uY%1zJSO~c{VaA2F#b{CTm2XOH^8?5KFZr-bBB6>wQm6nk16m` z-Vpy+^OpzwEx-pVdhYt=`zI5S5Fd-@SKD_4KDz!8?^ot9*4}yG>j58e5l|l%Q!qX) zJb+>MKg9dh@z(^tHo1Mo$8^!}e^s!0vA~DN$|!8?&^>f91>=_kUkdo>_&>?tYv3D@ z+h1(%P<&YX((n*#2K--X8_y31zB##lbbhe~YrhHj=>CW0?N`Td6>J#L_@nuUX)Y!P ztgapK(f$dW_t^Qr)4=K_0bdUIXzzf|VLFTDcL5)}|0B+?_FoV-Z2!&u-wF8W{*Cnq z&Ev%stbQh$kHw9Rz{9}CV{9^f3@S-EiKjJSocBGB9qe$i>?tilW`2Zi~ z9~*b9AE=GLDp>m$f&bq;zYGE&?VnJ)NE5B2iz!(9O7Oa^BAE}r{__0u01}EH>-S>E z0Bipw@O6NXj*$i$gT)k#{{#3Mxc)DOi|Sx}6L>LC7stoO@$Ymnej4zx{VU@9YW&ZE zuYv3TujWr49y&~ckK#u8!^Q!A{mX*Ip9p+3eyH8Wa*;5`uLeH;{;^mMj6Vl_4RZX8 z%{{(-OL%Za{Ke)CaZ$nAPY1px@UgftyHM-Te`5T8;N$l{f6n-4560()_cPG_56v6Y zf9(7}*ZyCRuzDuINBM_k6umyZ=z{T+fRCP^5fQrb%k9^bKDvKl*Z*R#A&mb9_-Ov2w*Qm%xna^_*FP2m>fhfLto<#($L_zV{lylHp9y?z za{m$cSNq=sd<}B{(b!|UNb9c(R*x6n+|mF(w*SM<{}mVcuzEhg$DY3z8#|s~1blS= zLAm=+_^*MF_Af{i&ELh20T#ay&jKI2Zm{!6@2?70ZwK(#k>f}87uyGnp9g%DKXi=Z zU+guA@q5Yfqwz!KSKHTu_jl3rAEt-d1+_o_iPa1K7yh3!{@H`^&jTM_KiKg<*ZT7# zto~QvYXX0<{l*kAzUs<_>mTv|ll%t(AB`W<#Wd0He^;=&SIK;A{{8CsPm}rBzU^1} z3h?GI7C%}8fA#vw0X};E!}^2uW3l~z1$;Sj{!rV$8vn9Y|A>FFv7^|qc+JRs)Gj*r ztL?`FeLFLvJlYx{Y? zNBR3tnV*Te9{O9%a?|7IWKPdl513Qnk z^Jf;T*9m-W;A8ujKdb+*=P~|Dp@sbar{ix4{7vNe7dv-RELi)efUgOB>=@->F$JqX z3Vd|`Mm&VY_5T<@_`86Q?jPvc3q60p%Yln382=pb(f%FXztA;+ zG!|1Zei!i3`h(^kJjyM)VEl_B1cKv#!Cx*)AXxqv{GGtp{V(`efv*94G=5Zz?)^W; z?>+F*_@T8QmBngc`IA`v&-*tN$6^Y`j{rUze{}t#G5po`uK^#ef9Sn~#kP&&!`lA} ze02SylYS3gZM)KQM+giezpBg zz(?~3#gDj{F8unJ1*;bheEk0DSKGe}eAItz{`_U5I49Qr4DiwVyV!BZBrv`>e6G|Q z_~_dGPwv0_{!6}q%-NDp2Hn7{w6BJ=PT`Qb5PzWh52O8|NgXTIPq8Y4aOd1TQwVn{wl7U>!RP(2d> zDtL?hrt@e2+M;@90HkjLK*w7FXinP#Q2BQjwQE1`U9gC^9e}I@`8?jD`c7p34zeFv zblwGkc&-3c@RlBqz2?s@SX9rOe2gsO`;w25MSef>G2Wu{{^aw>qW%T}(D`5hD#)UH zStvSy^6xCFA2#p(Ym4FvC)Yz3@gm5_$fDy&vfW2Mk1UGo0Qr10`8=|yehm5e-&y28 zNcJO(#xI_Hj4X;L5rFC?0Z>_tMfH>CYcE)&lR`d57Wq@jHjQl4!J>jJ@@D`LFOz(n z1r`-#k^eZ^W`jiqSycZ70QpanZ7x{Uud@Jj&$$Rd^)3TYK^E1&Lbg}Q_8M4JkVX8P z=l}|`G=Mt*q*Dn%1zDtXk8G>R_C8ot@D|m306?}HfC}Cs-5LNB;5h)b*8xEB_XAMD zTU38w{_MgJW-th-AdC3F?{g>{3->#echmW!zqY8J8Gs7#`#$&kK8L1E68ZrJSu{U> z-{%(ca33WF3f`jp{Qq~K`@!-9HSj-KK#zj3po^EL7QB-<_x$29!xIiy2r3;P3e5JZ zGK)VRlP!?m->a%HJ)wBcVOnzy4_oJIu8`Et#(lb`<2U4=hAHkK7=Cd)bm%2c7u~C| zLM>Z6FerI^Yd|>v)e93hHYz9UFqTLY`gZZkil{PIH}a@b3RW?XCap^-6e|ioYofOM z_Qt)b&&GA`9vkfX#;kY(r;F}USfLhqsz|IEWq7g9(q+O`O);FYI(%uptxr_MVJ#ZQ zXq%%C(i01Ys#Z(Bic`6*{5fPyx8~4!lQV?uXQY;A+$v!PI9;^2!3y=j`?Hh1QZaRb z3MY&CO^fVGvz*m>1`sG4fy8^U8{?>>TnqCdGlO< zqB~&y4yuP9tX}@N?>42ZGFj=%a6+>@y$q*|)@rO!^I1~&5_o@{(E0F*kS|eK$>P#C zI#R(jkT1n^bnG}4rTbiQSJ?8`&bxy$5BM7muGdN5>a;8!h@J6zj$cEyj$hzaNQgwsoH( zI^TEn`?^n9Ipq$;r#F%~UHtPC^=k73mA9vZG#QGv_^0LbTSswNdn%6Cs5Ge$eBK>Y zy#B&9!6EYu)5jvRcVn__Lut0l#)X%p3eF7NGvag~2|J6^MSEbZP;XmP{d#W*ag^So zI&nAe(8ojWk6rUs6r(N-_pUdqtTxzOZKt~N$FtPvahjlC3!;`4goGSV#W(uTtrfpp*^eC!4Avd*A zuj~E33(_7}R4$Z%FTWmrQ#IsKg)h%XFP!dDyzbre-OGzr<&U#n5}mthWw|@C`}|B| z+^wFMv1dzGPO9f-zV7}U=Mp7!-e#mlH0N~hT6U2udGab*HS7lhpQL{y;dB}Cx<(J8 z-pM_Bb?fQ&^!%7uVU$OgQFQI?=YYNx@f)9Vx6d)Lizsa^<4eRQPH<+ixf5W}3N_6yRsrzD-1S`>G# zRL$1J=(?`K>9XT>bqMq}HD=Eq2@XmR`PObd9{ zFR2paEh05ta*W~XS#K$md-d1UYPiKmFK`7b47w0|?}%T{EonS8^VuqYe=fr?P8WMU zVqTXbnX*5YmZk1lcSP}KZmJ}WJDLJ#8EK9%YIxg}Nm8iZKeqCDle07TO5Q62zTXuz zq%th-Yq{{KGhUGFer_*&AE%4Gjxn$6c1N>lrLx4zLdPwIN1EmwMJ!V))d#ZltBqH$ZRj-o}xF!|0I zWBKSVTYH=?7YdYIs1>@)rXNHTbXmp=U3Hh5ZA_n3o_?=GvKVf8)=by8?Bxx;*ioks z=?!epLu>2gEFM$eq!*Zr$aMjvjm9v|}{De&qqw>}VmtIaeiM?rAM;|#wJ@53tk6K5W~d(ToD?t1p)%1x&Ct%c`b zPm6tRw~FKou`4GT6)i2q>0+-hA$e+=_IHiLdv7p3;r2P0EU0IvH7oNnAldSDf55AT zOFVT_eQEtaMa9Z)hcvfQ7lc?OKDeB*p@24h>76mLi`Eif)p5G$^(d@R`|`f9IT(KL z81G;RjfvW*nix0rh-T{gh87tyD=UMl_-IQGW2Ug?`XHm3W}!Dl5jpK|A8i)4oxNqJ z;a)n^7>?6jiHU-x?wBJC^h!3dDuf!cjwIN{1QcA#89Q+`Z-DEA{cfEVq@yXq=Bitb zY@VjGTC#NTYdib5oXHNW>9kec>NtI>3a`tD*L{$=NjfCILG0qgS?v_#){(|3Bb!ly z@uuh%pCfv2Z}MFcy+LLdUt+KIJ(lUbww*Z}v-^Zcvqq^nGMl?Qee-wX;$4N;?NeWR zbU5$TQLEP$l)jGU8jT8DM2oem6!zOZ7*Dy`qnLdxtoVrSjgDHYrA(`KW=z!G_oj*% zdH*TJu+cSi{FNb2mmjY?6W$qgpZ)t|tE+So##*?Hk}={q_6kq zm;DCLy{Z?7;s}xh^6{+-Pt3p7eOGmV@m}COl^;%50I$2IBJ2f+3#IB>C3(4OtK0FB zKb8ndD!bltpe8&%*{1y9lWK3ygUlhDk3nzcHJYi_wn)YJM_%gFs+2rdL_-zFkJA;z z>&8hYuaw_$F?f!D*F)hS{^!+H9t+-Y(H^c~IDI_cDyzEUt7G~j9FCpgReOF(V}v?#m+3oQ zy|U9~)}0c;{?+aeI35xc^HkXUyB$u+T@CRJvhPV{FDSz43gdNO#N?WfFOzq?9n+_A zymU-5A-m9YJW244FNc=fh~Cq4cfYL39JrxDiXfcg4Z6vfa5#BTLqj|yI_I}sagMq1RJFOYa9-q#sK3ni2jV+gNN!hiv>^`+Z z-YAkj>)ePdKcyQZwe?-5XbhuBdl4(-Tn}IM}qM%#VA-lsle} zRrb3w+PL-Wx|vF|XZ88V)U{e9MK5LDNO*QHJ6QYS-P>zbbr1F6bXVhbc|WS(h)cL6 zC(q{QB>jnA!8y^%m+s+;4XP`@Ii3|P+}y~KlqT!xeKsoiFyTx`66c$@_eAqc%=+6s zv}lPQRbx2aHF(`8Zyc6ir$6#Cdb1YgW7_C<`P1(oy)8Nu?&v2GXLwh&>t2j-i@wL` zcHvVG)I6&X)cDSsG`N^OsJ6Fy)!V_g^Ab*146ke2yK2bF3F&lM@#mGva+GrEsu zY*^Rrpy%`5Hq>>PrFnlv7!3`T!1_};`XR2bUZ#dEG_XDH$Djwz}9wQ7|aMraXSCi{K??dM;^%Ph!T+uDSQTkU_7gzIDo{ zjnaCROrCeID@s4xOpDWnw}1X9)bxj_*IqeTTEigY>0G=<`dqzN@eP{(2E)XZu@#-E z8jibO+Ixzv&Gs^X^I~N;8{jA~lX|nT0(p4^&!OsV}&(+Y|GvvgF@;!|1 zTY4!?02eR3UGhhvK4BTuRAJc_m94i@j4r2f*ysVji_Rk}{d?4nR}W3MErCFaD6RK?y}!vi#X8f+w&mj@p@F36CJ-$%*)lWt$!_q(da39`%Uxae+= zMBaaJd1K9_Smw2*an_%;$NJaV@5?SaF|p;TeI)0J#t*i7`@RS*d80rXzp=5I`Pu;y zT)gsl-OQN6Z%STaN4{58#@uzNG=05hG{pGmm#!ZT5svzT#=32v3eAkRTV6XkF*(Jm zk|1AtfAc`OxW=dLdO?(T$C~|dx(ayR^!CG1$z@s@Y#Q7v{WK4mP$iQ>ENge$vRf`A zCNgqr$aos&wwfh2eBo=Jj(gNu;nAX~lIh#JZ_V50TGon?Ih?K{UiS>A-qE0ateMkv zZEx*4jO+{Z#!eid*Q0%^qRrzn9ndD$`f=-#2r~=u$SXg~ucV1v6YfPuxFt31%~rac zP!x9_r>lh59ViW@`LsLx{8QuOl{PtMY8^k^b56&_x0Dk?qw7~*3Os&J>8BPWr_PRm z`w^Z`D$lXM>hlWs^E~eU$)`Yg7eD@WjkS1Pr#cC_lEJ+t7uRY$4_Tl1-kM?hn)FMR zu(46vZ;HAnW1cgzm6w~-b8xqYiAFYwYTTm;c$+V**t6vAwl+_FlR8|y@Y%9I3U%I& z$gSKvY#*_vGK#(Tpypjta9ZBG7q-&{-Co?;yflyU*pGj4n|hx1`Qxz{Jj{*9#P+Qf zd~QRmx^C<7By1&q|FHfKRk+@+acaG=$`B0Bd$+RUL)zX-9<^O|=6?O{)YegyRn=U| z21#FO>$JW#mj>Uwn|IN|X*KW79n+gD#&7K_$*%T%+<}W1y$6dG>aAUMA8T($G`~11 z7@TR=s%{}xA{mz~GBCmF>#%i+3(fZMUE?2LbR2j$Z9Z7NCuuV;>GqE?1<%s0!_(tS zsi&H8y2_X+SnA44<+PWka#9{@dMAoW%+&k6Pkb_IdVkqL*0-rAqb0k8EApRxk)OEi z`&fCSl9*53j$oCrY(saoriKC;Ij*nWINgnS-62QL`t+QFAzS%t?RW@;<+>_v8Cv^YYpAo@ohr@=vL8x+-|xbwh~; zmrtdiofSQsrKRARW=j89;WHg`HV^OYrK$GbFA`L*)-mwdYWh)5@e2*4xY5XRz2P~_ z$W}E`DHx{K@Cm1@ir3ZEH`{db`sKVT4VLMIPLC%YER^w0lD6UpXatF|@SMbjI;;B?jSx;mPP3=eZ#pLqD}J(>?>89UPlJ4vYz3DF15t>BtBv#kUlvy9uv5 z{IPd-mCzxEDG1|uMCfhcHnP0mda^v?`Igh?_)>x7Ga80MLp9GX_=}kM;h?Y z^PBOycZXISq^)GJq>xmeJh=ITZ(Vn--Fu60uRU_Sl)1`dCUR1p7rL&eO6=)mUM4&n z7gc=8|Kk1Anr1Ezw#r-^Sn;oWYT|Xz-D`3oj@_VFxW?u`m6a%LuglR&$H6pt)TFj} zzYLX)&IrZu&(W9e#gr?K72cC&>SHNCbIq@^I9as5YkaxFATAGDcwKI$7+W55o91_4 z7*$=0orr1uYdMd*=ne*%xeZkif3V)Hd{#&Ep`i27;K;d**#;^e!&dR5^2-9=-8{bX z8n^RToUS%rSG~%WvSyMfn<224u49`XJ%#LK?6T1^j`&mqj<&c9cW(|=xhF<$D&{w? znDrWxoKn)-esk5v8p@}AXD623mcqX-r-Rpxt=hWQ@Tjq>h+PNYj>Pb?)@D87 zDcfCM-fD+E&9?5?-EttfHt>aPJ?n8hNyDZ}!wsKH%mjqR!u$*LAmy)21Oc|*1Pf38#T)9K6L@LzpJ zN`7C?nESRpdW9~vj{D~re}3pMASp#1?b8v`TrZ8&)yK!1fBU$nt#JO0VXla?OhU>( zE3M)wa^309ukb2c7o8d%q~;SYn!97@Wx(512exIQKXTrjdM%8kyu<3i#?jOHEtaq(iGCz;PfX@l;gXlye5OX* zC#=82B)h=3c8GWXE~g_O+jPU?d!pY>`APK0I#jW+Np5^qu^OjqgpW5lq)ldN%bAn6 zcZO#@N{cl)V9z`H_9U(BGJ{*$q?K(7m8V$63pC>84tyfz^7&Y4uG^m)%Uzi!zkz6c zmNr@de_a^kb&qlFt8$7@>tEs?^PtRXm*-xmLm8b%6ohwL^`_nCvFOP@DKI6~bv=JZO#u@A-<(9GgK^dPn5N1Zd&8=V2an>7j|?y zMqyelDu(MGf1Bpa_N7^Qn)GHb8HXE`XlaLdnW7N2XMOReQc~yPn4uLO3!F*KQYr_-YU0RrkAV3OlMqy-_EMkxm(rF!6n`@ zch#EQL!0ZuXX3j)a!FqNbiM9`M6=UH$@tZ?efZ}gb4(O0_1*Zr=4zIoJvVmjlZv@* zv~fn`_9WF+*}-&sZOf1)bBrhbB}|ri6C#99-ujV{!e$p!spDGu`LyX<6>82G0)*v1>hDKo70G;f#eYMx&`@GFW980$ zvC%(fg8bBq0{1tzTt7oUdPw0O+nJ~f^5+kT$pwAW*spAL#*9W*4X3*m69r5Cw8*tE z$f~kTfuZK}b?SW%3ODXv&d}6md{^x`_Vw80)qn&#PYPC5wy({tFE&Y7ocR!QgQ#&y zN4?YHUBC{NGlDo>OT2E-=W9Px|eq7Xz-W(!VoK z=kk2%?(V1D43Sfj7S9>ktzA!jYL!f=&WoTW;$MHT!t2V_Y3RPu*4mJ0GN|=_17ne= zpPs{J9hP3|pM^5*dy$_f_d~l45*7lD0N^BuUn9Wgj%rDZ2B4>o_OLVi~hn>;Sc+)<8?^Ix6Wd-lnhicAXo)8A=% z4~Y1=$EpHEZd#`oc zif;M&3(>OUJt9b#^IW~Y>3DFGJDc17OqdksuTbwA7`DJa2iW0t4N7tdT}-1UZSipr-G8V_zcEmV zRN!68`}l;|MMDL4$xB!J-ijWwSBbnH$#!^{g6iy${&J1++{*@f+*dO9jGe~i0sCAY zlBYh*+AMO8#ZpUa{8_U~!)veM=JNtm`>Se7J%>YGHKS#htMBXxo@9aqN34T&LiqqYWkC(b+y{W@i`@qS}yQ2LPH(f6a&0ZA0A9iuY^5v<9 z31z!G4qT_26Pvrtc_Vdzs!qYq+5ZfikLUg(L#6u+N{qI*`!Blgx3V@}@ueug$N1LHaY^C#{HFw&w95r)g-M3j zMOF#p;&sI99u42svySA_;eN4iC-cTpr|IBJd~Uo|AHLFyOKvF-4ZY&nwA#c zv+~F>FHUo=gx@Jb;9dTPM%!OyS*-A_QgxP;;L%BXrG5%mzK!g zCQ_X~u0(gjpKtg^u|sD}qudo<)2>$sR|MTSZEKu)Gfll=<+m_B-d3FM4!mx@a_)M= zlXKF-*X5;8C#hc1dQqI|CucyHE_`{I+3A(7Q)&}edGWT(E5uAw-#$9DB*%v%_G09l zjRl>DpI4P@$;CqO|Z9U^Dc%I53QaFgV3Ui z(b?01N6vbr4WBN)61JYZStG-`LWHYT|K)jKwpcf(d(V&1jTJTD(!O4*XZaeJ2Uomq z(V)4b<#ThFX{mh{Tf$UrmaZ6V;K^Mf_U^hx&J*g^tJ{|~u2(S@-z^eY&mZ{xn1RC9 z<@X{-HVl0~_naudnE}7=bHnStJ7PZJl3v5btyIG7%_rD=%l}%Dg?=oP+X*gJkAu(M z+Ag>p6x{QfX$j+LwKAh1Q@=Y|Kkj@|b3f+MUSj8davB#e5wFWAI`Qt%Kw-Vq_&P&Z z{}1QGD~htVy%Dm_E=^!AIl;z}w(vGv`IhR>{CS?N%Z0(X?Ib2HThYGemuoWwQI7@ zO7boH%6QI4>XS=Pn7`CLZrN{iaipVYx4j7GTqS9OVY21IUYxEcUbj+@YSRtdGnU-a zw`R4kB^R)?XT@wBDq3#GMJxWZ=gkN)Rkzs5;BIpRiN1JG_SPbcn!-mtSyAI{dJ>&{ zQXNA$T@qfGy02_WX13e|HSj%g+Y4`TFg0zRxtE%JcSUDE|GHop{~6=#Q!OY0=3|m&LMoxK`%tRGZxyKlN=r zdyenVckF^Kd=d{lpHEOmMC*urs~iwYD3^$>_L4urlCJ$|{mt5Y-ne*o;dNb_Z$`Uy z+m{m<2Lm_tuh-Afgy%|lVO-A2{QHLQaZH=TPt=I1yHn`2^u9e`@T$%$Dfx$2%u)`6 z%ZFO8s_w(*!3(d;{`_j*#My^J-?vTpAIUmoa@?Yc`}VdQUwdwhES<~H>02VP^Um7v zT%W*g4>wZ8-;w_Cy8V)2!*<~ePrJKywgUL|*c-1~FMD)IdVuCfEv?=jF<+kXmnLgn zb*0zERMRfE5PP)a$;ZpqREiop+xNUuBUyV`?iklS8Jro%?0GlAp)UKvQT+QCK6u>} z`;~>E8#YLUeOMi|Tc28dTgA^uXZlSTXx!?HBa*+jud-FTDw$|quWFax=cv0w*`tl) zTj_U}Yu1Lu2z^@l5nO(K@w$`E%?@gQ=_S?sRjaSx7B21#Y&Pm(8GAc-N8zkqc|?#r zgNJ+Jhl{MAH6Vycbb_urmG~zPTMb8)tEx6 zWIB?!MBOdUNdI~&t($uT)fg{5r*$7c@sh;l7R9eVmqg{3M5L=O58eOrez~;Q?VmVZ zf4pwowBhiOurG(ti;P7ltrRbS{FQspjO8$ZSFJG#CoC&l1 zSau+}x7foneCsJ!JsN?wtvKBPysq>a*HX@On&ir+RUXSe`uP_zHdrR7y{>c%+}x(x z=k>t&l+4M7Fb$p;9Y4DEZ9a0-_)yG9xL(1rcb(Ttvaj93zfTs3*ENaGKJoZHFO}}K zwB7!eovIA)U**c5+%sE5JlJ+kjN-{Af3tU)*D?-O@P&ODZr!T4d!V8P%KFFj&-dlCofuugQY{=F#&w|fQM_XPwQ{rZAFde}GOuoWRhlg{ zY#bz{OWiWhD{%g99a#`uLQY&$oCOU zy320jqwMN>TczU4?2ZWvmGvubWXII>MoeD|^IWn%Xc=|!V3NsW>`_&jzv@psrZQOs)gL6ImtTFz1C={>z z_-e#OAq_LTo+ME%U(cOlTORMYv!l$6Y0FC6-dH~t|FCtv_73Tkxk34@x8%P>y*t?Q zX8Fmo9vTg)I7hd1c6MC6VR&5~Hp)$p=8jB$@Xcm$ZlvLpAaQh!CI8s1Z23&QQc*p7 zjT4Pd|62Fs8=3sx)-HXS!kpRg-86jQqdu-=(W-%k+d^ zai3c+kgzL$>)d|Xxg7tL2<6??XX^T2PAXXEZr-PN%BV5s^bzIa{r=Y~G(M+a0&v57v^1 z(-LWwPr>Q#!|Rsb=4@AdyZ7i>PC}k47uCkTPeRZ3dS-LW_U{!H+^fKL^upV;7me*Y z2`)u8Rc|=?(gVYm%f<+|e<-{eK%wjEjMI(6>yCsOnCfm<87uo?_@h~W`^#{q$cpAc zt!;;LU!>hRu+Hv&qT5 zQ_nRSS^FdJDQ0V#EgS7q&zo&r9_f~3v^1$nkf+)vc1?Hk@sr*`>kNu}nzo#ia9DG; z;Fa^MeZDDd2Zx^GbPwQl+c&#=*geU~EWF)f%XYjprJj<}bJjeCf9$*4F~KiV#rJfL z#jkxW;&ETM;Vs8?Cs9L73bCu5)C1Ra?03n%AQs?sqw%_1sOZjA*ne>I%sLzV^A(Nd zjnTaLYU>uR-pffA65kpErkeQa!^$t@_T?Babyu1$4bu=eKjnb`Y=Y=tp;#WtHME{qt++F2X# zSo_JbtlgN;r)nj~xtHRbyX=}Ok0<5J+AlHVjNy>Fgn!P8#p|B7Ije5Na3lGEu}Yoo zeoMbbFUjvp4|Y)RlQjdvs%pqV86hjWHDnnb#9-AriUQur7)^zeCj@vdWH0>ZuG^{#`3 z+@cR|y<`d0zcHlaYgug8-f!^&ryGaYUFmf#?{()^frODp%e|-R4}|PtKXjFl^ijTJ zL}i#ZDbzNL_2c)4q33=|et)>f?(&VR_lBPyUYWR=TAljl3cE**INif|-O~}pA7%);>&Al*fW(G(D(9=x|nqJ(V&FditO3t>M=}{ z0xGlqf#!kX4gPmlZf=UNT8h zGG6zUd48n+#=Q@xG9(;IH#$mhmAEUQZKE`PWA8)lOv9u`?v}LHwGIjX`2FuuyzbQHHg+m{`vc*nb#3ah0xd1uwP+oDDYT2Y?%5s} z6W;LlXHYH6Qd9bP8(!A+Dvf4OG8O3rUfz2(t$yOhvsBZKxOh|Wx`aUi143?r(6*}Y zRl5Gy<}y4?#}CmQ3iNXQ@@DWoyt3HDH|ch>B(%?KX{U#G^@*8J#frkp+MgtkdVL|u z+MdDbrs8$&4BO8?OL=*&U(8)`!>zP(qD!03!F@~DPu}|O|0MKB`&Z_X60V}{T1R=~ z{G|@&4ZHSyJ$<&g%P;!yvjW8>f%wnaq~Ud=6mmWk7&E>6S(0luoc-pWnn(7#()f=w>jd*Y z(RkSu6{IMH-~VRdbyX-^1>Fs<$SSGy2UebIW0z3K6*AuSb~jH&;g*g0Z|7!NvY%Ye zHn3dQ-6C|r$3`ehTAdW7SjTg;l|S0ZZ5w|7dkn98MmF-G;sbL#j{}>zw@CHuYmpbe z?B{jbb920a+ViC*)2$iZq4}R>3YJ^#jl215IQ>)eYxUP(Uv9XO!@W0HYP}pT51Dw~ zOX+lz6#YAsCFCQXg@o@6jY*)p`#fLds1)lmLs3HtE}a#t*>z_#j;uMJbY6K%A@6#v zYJ9t_)wV5OL1|P6H{+jUv+%lWKWBK#E>Um&=3jF3VThE-a^)Q+rv3ZQoNZ!ym3`gT zJ(($MsbIz0?rvIn(opRC!jQdmwT4>N!B<-O`drGYH{;?xj@Nzrw)y=}MvkYIRI4>v zc32JPWcAOwXs)di)aGb?|3tQ(X4$tc#xWHxV%cCKTwhu z|9W*cURU@&$03QA;T656#%+B{7kR~lOC^&pYJ9w6d~(P)$b!mW(>U5e^L1ZkLIy(` z!!gpjw%pcBf{*Jx+_ih9xXSSRogBRGHFJ_k-JJPX^(v1OJ4W2P&MNF8T5=Bz?A^DV z_ukO@6rb?c%ice%%-RG$8y9|@iC>*l`lILcny+bR4xiRv#W{e>!wJ0Z4_&s0I~wif zpDd}Ue9)S%xn);rouz++Q{$T-)4~*I1MX;)4Agnisl}(hUMH>Bmi_&(Ek%jgJ(&@! zr@@q$s{LaAd4E)Z( z?+pCT!0!zF&cN>s{LaAd4E)Z(?+pCT!0!zF&cN>s{LaAd4E)Z(?+pCTz<-~C_vBB$ zdXhh>%Agt;;3`A%2@G=f@{;lLb=~Do@*>Ju1`vsx1Qg^10!d*+Uw0`1B>`tIl82A4 zJA7J`Tz>pqDCiJRD%^2HbHcM5hvoII8eK&9i$5%wIsktE9d{l3_V!X ztEB)GD-)m}@DjiQr~%Xh>Hv=b^?(LIBcKWJ81Mwp3_xL_zM($w0|Wqq0AYYA06t1V zSOX9Phyx@5k^pId3_unj2SEQHBKp4z6#+_swSaYi^?(h4jQ|yZDggc8Xz2ejQwMAY zXackV+5q?n6k#QR55Nh4kDd{@04o680A>JuMvA}&FadM|&H;h}A%Hyq^j(z%Kn4JP z-W`2c7k#f5eO4cR&jNiX!ViGHOXmeJ1jGUk0geD-0Q&$@fc=0lfG1!V0R6uf=>MQF z1sDKU0pO#5^M8lvI@lY4Qa~91eaA8jfaVtZzJw9L7!VCO0PqI*0CoVJ0ZsrjfH`0b z-~r$^0DV>+eJ{cn-~!kVumIcv+y$fowgM~xRsb8oHb5o79&is(1;_!g1JJy^0=Na( za0-4vxs$(O|89OFjU@n-SCpf002-GS05ncWAC1jY00V#$KmkB=7V&5SXiifB(7dJt zpz&k@ps{5FFanScCx8Qh@{8sH%AY%6H$ViS56}Sw15h4Oeslr00CfP$FB)F~02(_t z0LmZAHOdRh5y}Oldo)Ma0nnUBb5RU{u7lM8H0EfI@&b4O$d7V>ViExG z0|WuW03iUnj?i_p7N7`_1V{lC0CE6XfB--SAPqq0<;hS2s|;8V*Z@!kVAm4L2bKra zZt9&plYwM&LMaMtbgnNSXbo#dHrLAs!Y(-?4IZk zuS9dX=_njG$S5hvD9pFK6g(-ic8RM?)s(@bASbg{W<55aqaHOq8R0Q^lmX8=aL6sp zB#1c5y-U5sN_xYae|XTmpa;+1F^|V_?4v^9k(ZH|QBe5f8v?g1qxN25z3>G*5WxnJ z!@f_@>nLYYB6%wjJc=@M5Ze4qVgR*MqES+k2Z=7=Su3M}JZK)F{+voWVNth{GnJAe zQbA@d>JOSVtl+s&H$J9M!G3t&1A71X?uK;#imBdqiWo`?M1ABsCS3mMOQ zlw{z7T|u$%S#X0%I;-q4o@r8bH%nCk@W{!mlYtw_zl$2u2Ba$Bz=%i9G6|J(YUI7Aq__%aP*%by z7d-U7sQ8)%3)UVfL6+Be}-=C3VgY1O(2DpU;IQwm7Shm(+S)cp78cHZ3kF3Vq9wuiK zsw72?GAfVq=JzjS%8GITV=6~5qnTd~qI4&_Er*n7BFV9Vnj6`ZS($Tzeu~;--ZP)K zQ1GB0=gsY$*s5!HbUwEEx#LW`Fbb=M2G3R%sG)hVFxUj=ooH<#5I&owGi&r3ZU)af z8F>W=&WpGk-NFcpbfP8(#`Z_%)s)aYaP@Td+6A8GSNr9Rmv8R`4}^?*>PB=4M)$v@ zXoAuJPebjzM-kc$DQQkCLQcYU>+hd^OSB0 zoL8HV&BM#r#Thst6g?zGy zPiR26ieBgzc-BD#kkN}|k5$)zBs;%R*gR)Gqh;VhSEG5P*PY&L*DrzxT0s%qCwp>Z zZ);un&RjrN15Xp#Bg;bP!k=<|WL|B4_I7{=U2{3dMJi3w&VQO$o1bs5$R3|r zc384c7I?@RO3(F>f@Bz56az|~7+mb))dD@Ap`C#poV4@%ma5X=b#{>8{t`Af9vHk{-Sx0 zf{ZfkkBOo4x4s|mgg(s#aUKVc60G$w+SoVF3crMTeNHlRBCA0|^S23T&)p_*g2&cW z2R!Q`1mO7kxWYXQo<6T?9?#n2%m5xZkFH>nk2^e;dj@fylX@^Z__TH2Gannt$CDU9 z3JPS)9^qQi-wHDk^#zrGn`@XL@Pq?BMOQG*+l+NSS(h2fYS2zScv!(x(>PKZ>16Ex z56_>+hSn>;Py*rMiLNJW!gtS6QlLDe^5-5`Xaq&zExyX7DBZ=3k^-d~@dVixuAj$@ zCard*li~~G0~3Vc?i?884|eyUVT+t;qQiV_aMeMsiNS&JRZ;?rh>oRthSc_dWM>f6 zP=Dgx(y!g=uJ1=`^V5wm1s-(YIkZGP*W^qIy6Vx63&wO4`@(!v;n#NzOEol__bjY{ zf4a{7$&81g_>(mYqW+7uNTg($XtRFs0&UZ2=D_!GZYx%Yn;DIX+UBdtNUNyhl_*XSn3XSFS zPoYu40VHYkjnFkrQMKD8kHmr+><*CHpR6U2gBsvMm!i7jR{z*!A4fkQ^?W;BWYrk; zR$jxWkMzKU@&-}+1^a}$`nnOtH@O^M&rE}6FL|eG4>x#}9p?vvHF{axpXVc(zv|t< zgYHPX)Y9YpTYBrjL*CW=x#v&zA&Ri;G~CLb2j2V9 zW}%AugXRH5%>%b{bnn&R?9bYGk1k@KGvA*OPm-%AT#ZfMNi%26rgX_3P$LBr_n_O@ z1u2{Et?VNm|KN;+8k#!{!!~^Cc?nmEu?ZoilUq z%)R^W%uDbOlaM!G=ggTiXU^Bmd&5#&-g(FI-QMaaNDj!`0M$3Do)7MS+c)Za*mqH9 zt}Bq__0r(CH*df4p2d4fu8E_7K@TF9bj7Q8efW$2PL6Fr51mFx{55OkJhksk9DVto zI_)-b6fk||jeDL_FuQ9%|K^RymWBX>lRz-X&_mXF=aTO~cguwsJ!I$5)ASMno7#Br zO!LUqQ>TwH4AXY-CMhBHed~5izUA7j=uvv-_vj%xcz){euXbI0C$7K!eUDw7{S&ZZ5;~`ALF1)zr&^O&W1Ar=KtY!E zSiN#$2dVPW6@5HNB~{fPWYYE$(rgD;)HdX&wojx{?$+z4=vE`IyEhgKb& zq1c&X4ANDtn8U;5>1R$K|LXas!iJugk?JB{HTK@e-nIX;Z+$!Wuy1)DJ>(;u_~XyI zhrawOe3#5(Eca^olwjst;m4Calp+>vP@mWgXM|3DU#i*u#J5O}{-yKu*QU!99cU1PPHD)^Ao_(dOp7Q-0T0i--GmmHdqs6WZo^Y?YMCChsRcL zCLWMJKu-@nq$%Dowee%mU2*ss^eFBB3-l1S4Yk|<_1Y(f{>Ct@DJo zjT^DwkY~WapdEPN$4g7Co5t?bFqfmNsx{IFaCV?e^IYfZl~>)$_YoFdRn3Fym0pgv ztlpm=fkyIBzCQP)Xua@8X|o`UD^@I_=Q{K}`{(iR^?vZ;IVFi>8!h^+ZzRs%#{X9P zKX{v@dScJ2Cx3JPP0$pX&00=%)^o!VY!LoTsn6mCvEeo^hR1ZG zd}|?5o+dtHJNnO|Z^d7^e+a*`QlqwOUwm}?D{J;0Ns}aq=YsgIUk`ugBQqa*?J#nQ zWGz0ob@MM*E?o1U`xF)aSw=(my~xXtRi)*jPt&9mO^YN5rYFbPg@rK zxYbRC>{Me!x7};B!an^R^ThRDC>SUI#|S3Xgf$;&#=H_o@Yupe(+j8DK^^f@JMIbJ z^P534O}oi^YPC3MAU7N@j)dLLY%&tXjarrfuZg@UC_^+pk~ThRfm11UfTj8o#y9Z@a07E1IW zVA2)Amq3Im3?ktri=m%Hz1R;#$Lq@9_CjDyvt&Q?Wtk%%PrTya1p_Pu9GUfvj&){N zCV;xK5JqDsVgkAe5x$u<|_thUWRnRxpz>TT^9i`D}q`?Bo4T;&H=pAKA4t{ z6!yVFa1KuT3$XM7K)U%O$jLMjcp2p1UBk6ZD-=N-N3m|?F2T`h9L%%>KNX!I^`^bl zv&>l@N+g${!EB^jT(sxJ8FT=dQ3DHU%N;z(@feFFUg#zBRxloq3|2~(BC#yd7zIQ| zO-rD(gwpz1Flkc*M7jc9fryM2MtHIt-w}V-MpZTpn6e_<3fAI;M_NPt5SoP`Widr& zGv!?pQPM!Zw;3R6U;*}0zd5M}!{&6;Rup<^6vOJZy21++7@dVwq+T6z6GsUIt?SK) z6qX8@+aOF^onDN8ND4G19+CJ_H)u!GXc^(?1kOI^sPKNRH62hQSa9|y*w^#gn64Ll zZQ(~9LYNUFamD^5sql8IUYkiq=5gmp@7@HajTfbJf;{KweU>g zG9^UMV79U!=kk?G{4fOrSj{T5BVXtd0lceW-Fk9JwPglCbRG& zKl6aj%Vemf8t1%#fc(?Jk3tKg(nz2ywLlK=m!%6=?jEkjrr}vY+kiz#Y?7B@L9Yi% zrYZ=q6ijuju{a%3R+yg!)Md0dZ2(aIgaB@WZ{Xl;g5jM6yP$Y!S>19CqO=ZBs1oL6 zU(Y^ig;oQavZBMPNj~i8`YBG}>emeV+&)@aR|8kMNpRppbkQxXGy2kl2v-gP33jhe zUg-i(763!;i=886=K#UxZVN{9`GO^i1FuacO`5etc=aS|_pI?*c_`49n+DRI#_Yrc zO$$T2wm7?Q2544f#o-EHvm0!Nlb6{%pX*r2J7hq~0>ikNPIuLSpbv~!y5Dk~=oTO2 z=>uY^94@wi&Ir{Q1q?=wrNgCZNC5G$0FbH#C>7IN$Sr#`1TK9WtX72*<`{T02wH7% zHean18oFW!k}*om+67zPxdTX*cxPNv(1$EZy`qt|ABV<;k*No_DN1+;wWuXyReW@usQ~GKD4!R80U90tT@bs#%dm=g#Jbv`(} zG#}DU@se$~@-aY@mw9KLnwwvh5MQ`}(2|Uv{gjj4!h1&msgl5R$Bjy(QkW`cf+V$Y zE*}FFd6~j~x9OBGX8=|K{Og5bmGIy^=K4ZubX+o!|_Nwm6$tQ8r4xP5$o!Ed!jYNXn9-9jRd#{~Sz zme=V96Oxakxo(n>_EdgS}>Z{N4P)t{D;$3&eg!EPqu=FvI&C$dHN>>=x zDH8eG0jn9oe!ojBa&7@MFEgae0hB7SZ1eWXmyUczz{fUNz@@v*i8e+7pHX97 z?h*-OIzSsWKC>?9>|rKNtlntqm00#kJ=>IE^njB!6VJ8??niU&gxR3(TArQYnOmcQi%82$uvRcezJRFW>XgCyy7>1HE=!D>gg97S;;a26ZbfpL+O zJv;?;Rvc)@4SE4;)Bvr#6(%2x2;s)t0;0k=;tVZ2gX4q1T17U8UdQ%gLl4Rk5d?O| ztt;|JE&$ET47rhwy?TEzZ#za6PbClyxm>UuJ7%9}MMY7OU6v$F;XMzWINYoPhb-Xy z(X(5^(`PU#{-jU4d4toZo4sY+HiTXyz@0cDDbP@8N%8$eeYGSbO3RTP1RYklYzkwc zI5}RoB`@bMZ6YA@>?hX=Vc@d+~HK|!U^!D z7JVGabyjcUtheTJ3^2(8loGyj?2v1U7wY74$^t#nQ9{hl5w-HQvB3SZ^-9ec1#CtQ z>u@LC^2q?3mtkX6l8CdVeE(*V2t5c$bcJ>77GgsekHcI@@-e`Xm$3wQq|Vz%zK<-h zGs4`*rBPeN2#ajmR1YE!_YbDd`e0Rg7WwKFSPOLnYadYgBBY@I+bwJjwMd0k#2byjy y%a!zI_xn5Mn%X+OhlsF{&t>se>!E~LU=#7eIL1T(IGptBAyAR>0rdah|NjN?m@P;E diff --git a/frameworks/TypeScript/ditsmod/ditsmod-bun-mysql.dockerfile b/frameworks/TypeScript/ditsmod/ditsmod-bun-mysql.dockerfile index c6c56b41443..d0f44000dc7 100644 --- a/frameworks/TypeScript/ditsmod/ditsmod-bun-mysql.dockerfile +++ b/frameworks/TypeScript/ditsmod/ditsmod-bun-mysql.dockerfile @@ -6,7 +6,6 @@ RUN bun install RUN bun run build ENV NODE_ENV production -ENV IS_BUN true ENV DATABASE mysql ENV MYSQL_HOST tfb-database ENV MYSQL_USER benchmarkdbuser @@ -14,4 +13,4 @@ ENV MYSQL_PSWD benchmarkdbpass ENV MYSQL_DBNAME hello_world EXPOSE 8080 -CMD rm node_modules/@ditsmod/*/tsconfig.json && bun src/app/bun-integration/spawn.ts +CMD rm node_modules/@ditsmod/*/tsconfig.json && bun dist/main.js diff --git a/frameworks/TypeScript/ditsmod/ditsmod-bun-postgres.dockerfile b/frameworks/TypeScript/ditsmod/ditsmod-bun-postgres.dockerfile index 6d10f0bfc7b..1bcc29a8b2f 100644 --- a/frameworks/TypeScript/ditsmod/ditsmod-bun-postgres.dockerfile +++ b/frameworks/TypeScript/ditsmod/ditsmod-bun-postgres.dockerfile @@ -6,7 +6,6 @@ RUN bun install RUN bun run build ENV NODE_ENV production -ENV IS_BUN true ENV DATABASE postgres ENV PG_HOST tfb-database ENV PG_USER benchmarkdbuser @@ -14,4 +13,4 @@ ENV PG_PSWD benchmarkdbpass ENV PG_DBNAME hello_world EXPOSE 8080 -CMD rm node_modules/@ditsmod/*/tsconfig.json && bun src/app/bun-integration/spawn.ts +CMD rm node_modules/@ditsmod/*/tsconfig.json && bun dist/main.js diff --git a/frameworks/TypeScript/ditsmod/ditsmod-bun.dockerfile b/frameworks/TypeScript/ditsmod/ditsmod-bun.dockerfile index d18c49cab44..8f0268556af 100644 --- a/frameworks/TypeScript/ditsmod/ditsmod-bun.dockerfile +++ b/frameworks/TypeScript/ditsmod/ditsmod-bun.dockerfile @@ -6,7 +6,6 @@ RUN bun install RUN bun run build ENV NODE_ENV production -ENV IS_BUN true EXPOSE 8080 -CMD rm node_modules/@ditsmod/*/tsconfig.json && bun src/app/bun-integration/spawn.ts +CMD rm node_modules/@ditsmod/*/tsconfig.json && bun dist/main.js diff --git a/frameworks/TypeScript/ditsmod/package.json b/frameworks/TypeScript/ditsmod/package.json index 3d74a7822de..a4d1ec09851 100755 --- a/frameworks/TypeScript/ditsmod/package.json +++ b/frameworks/TypeScript/ditsmod/package.json @@ -10,16 +10,11 @@ "build": "tsc -b tsconfig.build.json", "clean": "rm -rf dist*" }, - "imports": { - "#routed/*": "./dist/app/modules/routed/*", - "#service/*": "./dist/app/modules/service/*", - "#utils/*": "./dist/app/utils/*" - }, "keywords": [], "author": "Костя Третяк", "license": "MIT", "dependencies": { - "@ditsmod/core": "~2.54.2", + "@ditsmod/core": "~2.55.0", "@ditsmod/routing": "~2.3.0", "handlebars": "^4.7.8", "lru-cache": "^11.0.0", diff --git a/frameworks/TypeScript/ditsmod/src/app/app.module.ts b/frameworks/TypeScript/ditsmod/src/app/app.module.ts index e0c1dfedcec..34bfc4357cf 100644 --- a/frameworks/TypeScript/ditsmod/src/app/app.module.ts +++ b/frameworks/TypeScript/ditsmod/src/app/app.module.ts @@ -1,13 +1,16 @@ -import { PreRouter, rootModule } from '@ditsmod/core'; +import { Providers, rootModule } from '@ditsmod/core'; +import { PRE_ROUTER_EXTENSIONS, RoutingModule } from '@ditsmod/routing'; -import { SimpleModule } from '#routed/simple/simple.module.js'; -import { BunPreRouter } from './bun-integration/pre-router.js'; -import { BunProviders } from './bun-integration/bun-providers.js'; +import { OneController } from './one.controller.js'; +import { DbService } from './db.service.js'; +import { InitExtension } from './init.extension.js'; +import { DB_INIT_EXTENSIONS } from './tokens.js'; +import { ModelService } from './types.js'; @rootModule({ - appends: [SimpleModule], - providersPerApp: [ - ...new BunProviders().useLogConfig({ level: 'off' }).if(process.env.IS_BUN).useClass(PreRouter, BunPreRouter), - ], + imports: [RoutingModule], + providersPerApp: new Providers().passThrough(DbService).passThrough(ModelService).useLogConfig({ level: 'off' }), + extensions: [{ extension: InitExtension, groupToken: DB_INIT_EXTENSIONS, nextToken: PRE_ROUTER_EXTENSIONS }], + controllers: [OneController], }) export class AppModule {} diff --git a/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-application.ts b/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-application.ts deleted file mode 100644 index 0b462db87bb..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-application.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AnyFn, AppInitializer, Application } from '@ditsmod/core'; -import { Serve, Server } from 'bun'; - -export class BunApplication extends Application { - protected override createServer(requestListener: any): any { - const serveOptions = this.appOptions.serverOptions as Serve; - serveOptions.fetch ??= (req) => requestListener(req); - return Bun.serve(serveOptions); - } - - protected override async createServerAndBindToListening(appInitializer: AppInitializer, resolve: AnyFn) { - this.flushLogs(); - const server = (await this.createServer(appInitializer.requestListener)) as Server; - this.systemLogMediator.serverListen(this, server.hostname, server.port); - resolve({ server }); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-providers.ts b/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-providers.ts deleted file mode 100644 index 0581973f421..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/bun-integration/bun-providers.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Providers, Class } from '@ditsmod/core'; - -export class BunProviders extends Providers { - protected setCondition?: boolean; - protected ifCondition?: boolean; - - if(condition: any) { - this.setCondition = true; - this.ifCondition = condition; - return this; - } - - override useClass(token: A, useClass: B, multi?: boolean): this { - if (!this.setCondition || this.ifCondition) { - this.pushProvider({ token, useClass }, multi); - } - this.setCondition = undefined; - this.ifCondition = undefined; - return this; - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/bun-integration/node-res.ts b/frameworks/TypeScript/ditsmod/src/app/bun-integration/node-res.ts deleted file mode 100644 index 7dae8de27a6..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/bun-integration/node-res.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Writable } from 'node:stream'; - -export class NodeRes extends Writable { - #chunks: Buffer[] = []; - #resolve: (body: string) => void; - status: number = 200; - headers = {} as HeadersInit; - body = new Promise((resolve) => (this.#resolve = resolve)); - headersSent?: boolean; - statusText?: string; - - set statusCode(statusCode: number) { - this.status = statusCode; - } - - getHeader(name: string) { - return this.headers[name as keyof HeadersInit]; - } - - getHeaders() { - return this.headers; - } - - setHeader(name: string, value: number | string | readonly string[]) { - this.headers = { ...this.headers, [name]: value } as HeadersInit; - return this; - } - - writeHead(statusCode: number, headers?: HeadersInit): this; - writeHead(statusCode: number, statusMessage: string, headers?: HeadersInit): this; - writeHead(statusCode: number, statusMsgOrHeaders?: string | HeadersInit, headers?: HeadersInit): this { - this.status = statusCode; - if (typeof statusMsgOrHeaders == 'object') { - this.mergeHeaders(statusMsgOrHeaders); - } else { - this.statusText = statusMsgOrHeaders; - this.mergeHeaders(headers); - } - return this; - } - - override _write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void { - this.#chunks.push(Buffer.from(chunk)); - callback(); - } - - override _final(callback: (error?: Error | null) => void): void { - const finalData = Buffer.concat(this.#chunks); - this.headersSent = true; - this.#resolve(finalData.toString()); - callback(); - } - - protected mergeHeaders(headers: HeadersInit = {}) { - if (Array.isArray(headers)) { - headers.forEach(([key, val]) => ((this.headers as any)[key] = val)); - } else { - this.headers = { ...this.headers, ...headers }; - } - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/bun-integration/pre-router.ts b/frameworks/TypeScript/ditsmod/src/app/bun-integration/pre-router.ts deleted file mode 100644 index 26a0100e4e0..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/bun-integration/pre-router.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { PreRouter } from '@ditsmod/core'; -import { NodeRes } from './node-res.js'; - -export class BunPreRouter extends PreRouter { - override requestListener: any = async (req: Request) => { - const nodeReq = req as any; - const nodeRes = new NodeRes(); - - const url = new URL(req.url); - const uri = url.pathname; - const queryString = url.search.slice(1); - const { handle, params } = this.router.find(req.method as any, uri); - if (!handle) { - this.sendNotImplemented(nodeRes as any); - const body = await nodeRes.body; - return new Response(body, nodeRes); - } - - await handle(nodeReq, nodeRes as any, params!, queryString).catch((err) => { - this.sendInternalServerError(nodeRes as any, err); - }); - - const body = await nodeRes.body; - return new Response(body, nodeRes); - }; -} diff --git a/frameworks/TypeScript/ditsmod/src/app/bun-integration/spawn.ts b/frameworks/TypeScript/ditsmod/src/app/bun-integration/spawn.ts deleted file mode 100644 index 439451029a4..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/bun-integration/spawn.ts +++ /dev/null @@ -1,9 +0,0 @@ -import os from 'node:os'; - -const numCPUs = os.cpus().length; -for (let i = 0; i < numCPUs; i++) { - Bun.spawn(['bun', 'dist/main.bun.js'], { - stdio: ['inherit', 'inherit', 'inherit'], - env: { ...process.env }, - }); -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.service.ts b/frameworks/TypeScript/ditsmod/src/app/db.service.ts similarity index 96% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.service.ts rename to frameworks/TypeScript/ditsmod/src/app/db.service.ts index 61c9b5bbfbd..1267c11f360 100644 --- a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.service.ts +++ b/frameworks/TypeScript/ditsmod/src/app/db.service.ts @@ -1,8 +1,8 @@ import { injectable } from '@ditsmod/core'; import { LRUCache } from 'lru-cache'; -import { getNumberOfObjects, getRandomNumber } from '#utils/helper.js'; import { ModelService, World } from './types.js'; +import { getNumberOfObjects, getRandomNumber } from './helper.js'; @injectable() export class DbService { diff --git a/frameworks/TypeScript/ditsmod/src/app/utils/helper.ts b/frameworks/TypeScript/ditsmod/src/app/helper.ts similarity index 90% rename from frameworks/TypeScript/ditsmod/src/app/utils/helper.ts rename to frameworks/TypeScript/ditsmod/src/app/helper.ts index 33a0cb20ad6..3adcffe4fef 100644 --- a/frameworks/TypeScript/ditsmod/src/app/utils/helper.ts +++ b/frameworks/TypeScript/ditsmod/src/app/helper.ts @@ -1,4 +1,4 @@ -import { Fortune } from '#service/db/types.js'; +import { Fortune } from './types.js'; export function getRandomNumber() { return Math.floor(Math.random() * 10000) + 1; diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/init.extension.ts b/frameworks/TypeScript/ditsmod/src/app/init.extension.ts similarity index 100% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/init.extension.ts rename to frameworks/TypeScript/ditsmod/src/app/init.extension.ts diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller.ts deleted file mode 100644 index ac39c4bc715..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AnyObj, controller, inject, QUERY_PARAMS, Res, route } from '@ditsmod/core'; - -import { DbService } from '#service/db/db.service.js'; -import { getRandomNumber } from '#utils/helper.js'; - -@controller() -export class DbController { - constructor( - private res: Res, - private dbService: DbService, - ) { - res.nodeRes.setHeader('Server', 'Ditsmod'); - } - - @route('GET', 'db') - async getSingleQuery() { - const id = getRandomNumber(); - const result = await this.dbService.findOneWorld(id); - this.res.sendJson(result); - } - - @route('GET', 'queries') - async getMultiQueries(@inject(QUERY_PARAMS) queryParams: AnyObj) { - const result = await this.dbService.getMultiQueries(queryParams.queries); - this.res.sendJson(result); - } - - @route('GET', 'cached-queries') - async getCachedWorlds(@inject(QUERY_PARAMS) queryParams: AnyObj) { - const result = await this.dbService.getMultiQueries(queryParams.count, false); - this.res.sendJson(result); - } - - @route('GET', 'updates') - async getUpdates(@inject(QUERY_PARAMS) queryParams: AnyObj) { - const worlds = await this.dbService.saveWorlds(queryParams.queries); - this.res.sendJson(worlds); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller2.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller2.ts deleted file mode 100644 index cef38bd4d0b..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/db.controller2.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AnyObj, controller, RequestContext, SingletonRequestContext, route } from '@ditsmod/core'; - -import { DbService } from '#service/db/db.service.js'; -import { getRandomNumber } from '#utils/helper.js'; - -@controller({ isSingleton: true }) -export class DbController2 { - constructor(private dbService: DbService) {} - - @route('GET', 'db2') - async getSingleQuery(ctx: RequestContext) { - const id = getRandomNumber(); - const result = await this.dbService.findOneWorld(id); - this.sendJson(ctx, result); - } - - @route('GET', 'queries2') - async getMultiQueries(ctx: SingletonRequestContext) { - const result = await this.dbService.getMultiQueries(ctx.queryParams!.queries); - this.sendJson(ctx, result); - } - - @route('GET', 'cached-queries2') - async getCachedWorlds(ctx: SingletonRequestContext) { - const result = await this.dbService.getMultiQueries(ctx.queryParams!.count, false); - this.sendJson(ctx, result); - } - - @route('GET', 'updates2') - async getUpdates(ctx: SingletonRequestContext) { - const worlds = await this.dbService.saveWorlds(ctx.queryParams!.queries); - this.sendJson(ctx, worlds); - } - - protected sendJson(ctx: RequestContext, value: AnyObj) { - ctx.nodeRes.setHeader('Server', 'Ditsmod'); - ctx.nodeRes.setHeader('Content-Type', 'application/json; charset=utf-8'); - ctx.nodeRes.end(JSON.stringify(value)); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller.ts deleted file mode 100644 index 64c6b087cc5..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller.ts +++ /dev/null @@ -1,41 +0,0 @@ -import Handlebars from 'handlebars'; -import { NODE_RES, NodeResponse, controller, inject, route } from '@ditsmod/core'; - -import { additionalFortune, compare } from '#utils/helper.js'; -import { DbService } from '#service/db/db.service.js'; - -const tmpl = Handlebars.compile( - [ - '', - '', - 'Fortunes', - '', - '', - '', - '', - '', - '', - '{{#fortunes}}', - '', - '', - '', - '', - '{{/fortunes}}', - '
idmessage
{{id}}{{message}}
', - '', - '', - ].join(''), -); - -@controller() -export class FortuneController { - @route('GET', 'fortunes') - async fortunes(@inject(NODE_RES) nodeRes: NodeResponse, dbService: DbService) { - const fortunes = await dbService.findAllFortunes(); - fortunes.push(additionalFortune); - fortunes.sort(compare); - nodeRes.setHeader('Server', 'Ditsmod'); - nodeRes.setHeader('Content-Type', 'text/html; charset=utf-8'); - nodeRes.end(tmpl({ fortunes })); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller2.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller2.ts deleted file mode 100644 index 5100a0dcb54..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/fortune.controller2.ts +++ /dev/null @@ -1,43 +0,0 @@ -import Handlebars from 'handlebars'; -import { RequestContext, controller, route } from '@ditsmod/core'; - -import { additionalFortune, compare } from '#utils/helper.js'; -import { DbService } from '#service/db/db.service.js'; - -const tmpl = Handlebars.compile( - [ - '', - '', - 'Fortunes', - '', - '', - '', - '', - '', - '', - '{{#fortunes}}', - '', - '', - '', - '', - '{{/fortunes}}', - '
idmessage
{{id}}{{message}}
', - '', - '', - ].join(''), -); - -@controller({ isSingleton: true }) -export class FortuneController2 { - constructor(private dbService: DbService) {} - - @route('GET', 'fortunes2') - async fortunes(ctx: RequestContext) { - const fortunes = await this.dbService.findAllFortunes(); - fortunes.push(additionalFortune); - fortunes.sort(compare); - ctx.nodeRes.setHeader('Server', 'Ditsmod'); - ctx.nodeRes.setHeader('Content-Type', 'text/html; charset=utf-8'); - ctx.nodeRes.end(tmpl({ fortunes })); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/simple.module.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/simple.module.ts deleted file mode 100644 index 123681d91aa..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/simple.module.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { featureModule } from '@ditsmod/core'; -import { RoutingModule } from '@ditsmod/routing'; - -import { DbModule } from '#service/db/db.module.js'; -import { WithoutDbController } from './without-db.controller.js'; -import { DbController } from './db.controller.js'; -import { FortuneController } from './fortune.controller.js'; -import { SingletonController } from './singleton.controller.js'; -import { DbController2 } from './db.controller2.js'; -import { FortuneController2 } from './fortune.controller2.js'; - -@featureModule({ - imports: [RoutingModule, DbModule], - controllers: [ - WithoutDbController, - DbController, - DbController2, - FortuneController, - FortuneController2, - SingletonController, - ], -}) -export class SimpleModule {} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/singleton.controller.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/singleton.controller.ts deleted file mode 100644 index 3661775e536..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/singleton.controller.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { controller, route, SingletonRequestContext } from '@ditsmod/core'; - -@controller({ isSingleton: true }) -export class SingletonController { - @route('GET', 'plaintext2') - getHello(ctx: SingletonRequestContext) { - ctx.nodeRes.setHeader('Server', 'Ditsmod'); - ctx.nodeRes.setHeader('Content-Type', 'text/plain; charset=utf-8'); - ctx.nodeRes.end('Hello, World!'); - } - - @route('GET', 'json2') - getJson(ctx: SingletonRequestContext) { - ctx.nodeRes.setHeader('Server', 'Ditsmod'); - ctx.nodeRes.setHeader('Content-Type', 'application/json; charset=utf-8'); - ctx.nodeRes.end(JSON.stringify({ message: 'Hello, World!' })); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/without-db.controller.ts b/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/without-db.controller.ts deleted file mode 100644 index 9ff5246609f..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/routed/simple/without-db.controller.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { controller, Res, route } from '@ditsmod/core'; - -@controller() -export class WithoutDbController { - constructor(private res: Res) { - res.nodeRes.setHeader('Server', 'Ditsmod'); - } - - @route('GET', 'plaintext') - getHello() { - this.res.send('Hello, World!'); - } - - @route('GET', 'json') - getJson() { - this.res.sendJson({ message: 'Hello, World!' }); - } -} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.module.ts b/frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.module.ts deleted file mode 100644 index 08de21fb22a..00000000000 --- a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/db.module.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { featureModule } from '@ditsmod/core'; -import { PRE_ROUTER_EXTENSIONS } from '@ditsmod/routing'; - -import { DbService } from './db.service.js'; -import { InitExtension } from './init.extension.js'; -import { DB_INIT_EXTENSIONS } from './tokens.js'; -import { ModelService } from './types.js'; - -@featureModule({ - providersPerApp: [DbService, ModelService], - extensions: [{ extension: InitExtension, groupToken: DB_INIT_EXTENSIONS, nextToken: PRE_ROUTER_EXTENSIONS }], -}) -export class DbModule {} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/mysql.service.ts b/frameworks/TypeScript/ditsmod/src/app/mysql.service.ts similarity index 100% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/mysql.service.ts rename to frameworks/TypeScript/ditsmod/src/app/mysql.service.ts diff --git a/frameworks/TypeScript/ditsmod/src/app/one.controller.ts b/frameworks/TypeScript/ditsmod/src/app/one.controller.ts new file mode 100644 index 00000000000..09615c93598 --- /dev/null +++ b/frameworks/TypeScript/ditsmod/src/app/one.controller.ts @@ -0,0 +1,88 @@ +import { AnyObj, controller, RequestContext, SingletonRequestContext, route } from '@ditsmod/core'; +import Handlebars from 'handlebars'; + +import { DbService } from './db.service.js'; +import { additionalFortune, compare, getRandomNumber } from './helper.js'; + +const tmpl = Handlebars.compile( + [ + '', + '', + 'Fortunes', + '', + '', + '', + '', + '', + '', + '{{#fortunes}}', + '', + '', + '', + '', + '{{/fortunes}}', + '
idmessage
{{id}}{{message}}
', + '', + '', + ].join(''), +); + +@controller({ isSingleton: true }) +export class OneController { + constructor(private dbService: DbService) {} + + @route('GET', 'db') + async getSingleQuery(ctx: RequestContext) { + const id = getRandomNumber(); + const result = await this.dbService.findOneWorld(id); + this.sendJson(ctx, result); + } + + @route('GET', 'queries') + async getMultiQueries(ctx: SingletonRequestContext) { + const result = await this.dbService.getMultiQueries(ctx.queryParams!.queries); + this.sendJson(ctx, result); + } + + @route('GET', 'cached-queries') + async getCachedWorlds(ctx: SingletonRequestContext) { + const result = await this.dbService.getMultiQueries(ctx.queryParams!.count, false); + this.sendJson(ctx, result); + } + + @route('GET', 'updates') + async getUpdates(ctx: SingletonRequestContext) { + const worlds = await this.dbService.saveWorlds(ctx.queryParams!.queries); + this.sendJson(ctx, worlds); + } + + @route('GET', 'fortunes') + async fortunes(ctx: RequestContext) { + const fortunes = await this.dbService.findAllFortunes(); + fortunes.push(additionalFortune); + fortunes.sort(compare); + ctx.nodeRes.setHeader('Server', 'Ditsmod'); + ctx.nodeRes.setHeader('Content-Type', 'text/html; charset=utf-8'); + ctx.nodeRes.end(tmpl({ fortunes })); + } + + @route('GET', 'plaintext') + getHello(ctx: SingletonRequestContext) { + ctx.nodeRes.setHeader('Server', 'Ditsmod'); + ctx.nodeRes.setHeader('Content-Type', 'text/plain; charset=utf-8'); + ctx.nodeRes.end('Hello, World!'); + } + + @route('GET', 'json') + getJson(ctx: SingletonRequestContext) { + ctx.nodeRes.setHeader('Server', 'Ditsmod'); + ctx.nodeRes.setHeader('Content-Type', 'application/json; charset=utf-8'); + ctx.nodeRes.end(JSON.stringify({ message: 'Hello, World!' })); + } + + protected sendJson(ctx: RequestContext, value: AnyObj) { + ctx.nodeRes.setHeader('Server', 'Ditsmod'); + ctx.nodeRes.setHeader('Content-Type', 'application/json; charset=utf-8'); + ctx.nodeRes.end(JSON.stringify(value)); + } +} diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/postgres.service.ts b/frameworks/TypeScript/ditsmod/src/app/postgres.service.ts similarity index 100% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/postgres.service.ts rename to frameworks/TypeScript/ditsmod/src/app/postgres.service.ts diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/tokens.ts b/frameworks/TypeScript/ditsmod/src/app/tokens.ts similarity index 100% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/tokens.ts rename to frameworks/TypeScript/ditsmod/src/app/tokens.ts diff --git a/frameworks/TypeScript/ditsmod/src/app/modules/service/db/types.ts b/frameworks/TypeScript/ditsmod/src/app/types.ts similarity index 100% rename from frameworks/TypeScript/ditsmod/src/app/modules/service/db/types.ts rename to frameworks/TypeScript/ditsmod/src/app/types.ts diff --git a/frameworks/TypeScript/ditsmod/src/main.bun.ts b/frameworks/TypeScript/ditsmod/src/main.bun.ts deleted file mode 100644 index 42c0798a066..00000000000 --- a/frameworks/TypeScript/ditsmod/src/main.bun.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Serve, Server } from 'bun'; - -import { AppModule } from './app/app.module.js'; -import { BunApplication } from './app/bun-integration/bun-application.js'; - -const reusePort = process.env.NODE_ENV == 'production'; -const serverOptions = { port: 8080, hostname: '0.0.0.0', reusePort } as Serve; -const { server } = await new BunApplication().bootstrap(AppModule, { - serverOptions: serverOptions as any, -}); - -const bunServer = server as unknown as Server; diff --git a/frameworks/TypeScript/ditsmod/tsconfig.json b/frameworks/TypeScript/ditsmod/tsconfig.json index ef1b58e6cb3..34983f83409 100644 --- a/frameworks/TypeScript/ditsmod/tsconfig.json +++ b/frameworks/TypeScript/ditsmod/tsconfig.json @@ -17,12 +17,6 @@ "strictPropertyInitialization": false, "allowJs": false, "types": ["bun-types"], - // Bun works with bugs if this code is uncommented. - // "paths": { - // "#routed/*": ["./src/app/modules/routed/*"], - // "#service/*": ["./src/app/modules/service/*"], - // "#utils/*": ["./src/app/utils/*"], - // } }, "include": [ "src", From 404f8899abaa38b6b745b3435b54533991df9eea Mon Sep 17 00:00:00 2001 From: Sanskar Jethi <29942790+sansyrox@users.noreply.github.com> Date: Mon, 26 Aug 2024 17:28:20 +0100 Subject: [PATCH 06/40] chore: update robyn to latest version (#9217) * chore: update robyn to latest version * update v number --- frameworks/Python/robyn/app-const.py | 18 +++++++----------- frameworks/Python/robyn/app.py | 17 +++++++---------- frameworks/Python/robyn/benchmark_config.json | 3 ++- frameworks/Python/robyn/requirements-const.txt | 2 +- frameworks/Python/robyn/requirements.txt | 2 +- frameworks/Python/robyn/robyn-const.dockerfile | 2 +- frameworks/Python/robyn/robyn.dockerfile | 2 +- 7 files changed, 20 insertions(+), 26 deletions(-) diff --git a/frameworks/Python/robyn/app-const.py b/frameworks/Python/robyn/app-const.py index e082ff1b129..4b806389fa5 100755 --- a/frameworks/Python/robyn/app-const.py +++ b/frameworks/Python/robyn/app-const.py @@ -1,15 +1,15 @@ import multiprocessing import os -from robyn import Response, Robyn, jsonify +from robyn import Response, Robyn from robyn.argument_parser import Config class SpecialConfig(Config): def __init__(self): super().__init__() - self.workers = 2 - self.processes = (os.cpu_count() * 2) + 1 + self.workers = (os.cpu_count() * 2) + 1 + self.processes = os.cpu_count() self.log_level = "WARN" @@ -22,16 +22,12 @@ def plaintext() -> str: @app.get("/json", const=True) -def json() -> str: - return Response( - status_code=200, - description=jsonify({"message": "Hello, world!"}), - headers={"Content-Type": "application/json"} - ) - +def json() -> dict: + return { + "message": "Hello, world!" + } if __name__ == "__main__": app.add_response_header("Server", "Robyn") - app.start(host="0.0.0.0", port=8080) diff --git a/frameworks/Python/robyn/app.py b/frameworks/Python/robyn/app.py index 798b67026e2..e8c975e530f 100755 --- a/frameworks/Python/robyn/app.py +++ b/frameworks/Python/robyn/app.py @@ -1,15 +1,15 @@ import multiprocessing import os -from robyn import Response, Robyn, jsonify +from robyn import Response, Robyn from robyn.argument_parser import Config class SpecialConfig(Config): def __init__(self): super().__init__() - self.workers = 2 - self.processes = (os.cpu_count() * 2) + 1 + self.workers = (os.cpu_count() * 2) + 1 + self.processes = os.cpu_count() self.log_level = "WARN" @@ -22,13 +22,10 @@ def plaintext() -> str: @app.get("/json") -def json() -> str: - return Response( - status_code=200, - description=jsonify({"message": "Hello, world!"}), - headers={"Content-Type": "application/json"} - ) - +def json() -> dict: + return { + "message": "Hello, world!" + } if __name__ == "__main__": app.add_response_header("Server", "Roby1n") diff --git a/frameworks/Python/robyn/benchmark_config.json b/frameworks/Python/robyn/benchmark_config.json index 3d8c6baa8a3..46cd72fe4c6 100755 --- a/frameworks/Python/robyn/benchmark_config.json +++ b/frameworks/Python/robyn/benchmark_config.json @@ -38,4 +38,5 @@ } } ] -} \ No newline at end of file +} + diff --git a/frameworks/Python/robyn/requirements-const.txt b/frameworks/Python/robyn/requirements-const.txt index 0056c1d2876..fbb88344955 100644 --- a/frameworks/Python/robyn/requirements-const.txt +++ b/frameworks/Python/robyn/requirements-const.txt @@ -1,2 +1,2 @@ uvloop==0.19.0 -robyn==0.45.0 +robyn==0.60.2 diff --git a/frameworks/Python/robyn/requirements.txt b/frameworks/Python/robyn/requirements.txt index 0056c1d2876..fbb88344955 100644 --- a/frameworks/Python/robyn/requirements.txt +++ b/frameworks/Python/robyn/requirements.txt @@ -1,2 +1,2 @@ uvloop==0.19.0 -robyn==0.45.0 +robyn==0.60.2 diff --git a/frameworks/Python/robyn/robyn-const.dockerfile b/frameworks/Python/robyn/robyn-const.dockerfile index a12c64e248f..90b201eccff 100644 --- a/frameworks/Python/robyn/robyn-const.dockerfile +++ b/frameworks/Python/robyn/robyn-const.dockerfile @@ -8,4 +8,4 @@ RUN pip3 install -r /robyn/requirements-const.txt EXPOSE 8080 -CMD ["python", "app-const.py", "--log-level", "warn"]] +CMD ["robyn", "app-const.py", "--fast"] diff --git a/frameworks/Python/robyn/robyn.dockerfile b/frameworks/Python/robyn/robyn.dockerfile index bc42b5be462..8de6fea2c19 100644 --- a/frameworks/Python/robyn/robyn.dockerfile +++ b/frameworks/Python/robyn/robyn.dockerfile @@ -8,4 +8,4 @@ RUN pip3 install -r /robyn/requirements.txt EXPOSE 8080 -CMD ["python", "app.py", "--log-level", "warn"] +CMD ["robyn", "app.py", "--fast"] From 3db2b8d977018b4af298255739b12ca20311513a Mon Sep 17 00:00:00 2001 From: itrofimow Date: Mon, 26 Aug 2024 20:28:36 +0400 Subject: [PATCH 07/40] [C++] [userver] bump userver commit, improve application scalability (#9219) * bump userver commit * improve scalability * fix the configs --- frameworks/C++/userver/userver-bare.dockerfile | 2 +- frameworks/C++/userver/userver.dockerfile | 2 +- frameworks/C++/userver/userver_configs/static_config.yaml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frameworks/C++/userver/userver-bare.dockerfile b/frameworks/C++/userver/userver-bare.dockerfile index a318a9601b7..92f8cdaa080 100644 --- a/frameworks/C++/userver/userver-bare.dockerfile +++ b/frameworks/C++/userver/userver-bare.dockerfile @@ -6,7 +6,7 @@ RUN apt update && \ WORKDIR /src RUN git clone https://github.com/userver-framework/userver.git && \ - cd userver && git checkout ec1a3b07793f8d4cd0968cd61d8e6079d667a1e7 + cd userver && git checkout bdd5e1e03921ff378b062f86a189c3cfa3d66332 COPY userver_benchmark/ ./ RUN mkdir build && cd build && \ diff --git a/frameworks/C++/userver/userver.dockerfile b/frameworks/C++/userver/userver.dockerfile index 9b45edd2418..5f4755e3714 100644 --- a/frameworks/C++/userver/userver.dockerfile +++ b/frameworks/C++/userver/userver.dockerfile @@ -6,7 +6,7 @@ RUN apt update && \ WORKDIR /src RUN git clone https://github.com/userver-framework/userver.git && \ - cd userver && git checkout ec1a3b07793f8d4cd0968cd61d8e6079d667a1e7 + cd userver && git checkout bdd5e1e03921ff378b062f86a189c3cfa3d66332 COPY userver_benchmark/ ./ RUN mkdir build && cd build && \ diff --git a/frameworks/C++/userver/userver_configs/static_config.yaml b/frameworks/C++/userver/userver_configs/static_config.yaml index 2bdcf1fbce5..4d7a7878912 100644 --- a/frameworks/C++/userver/userver_configs/static_config.yaml +++ b/frameworks/C++/userver/userver_configs/static_config.yaml @@ -1,8 +1,7 @@ # yaml components_manager: event_thread_pool: - threads: 9 - dedicated_timer_threads: 1 + threads: 8 coro_pool: initial_size: 10000 # Preallocate 10000 coroutines at startup. max_size: 300000 # Do not keep more than 300000 preallocated coroutines. @@ -12,8 +11,9 @@ components_manager: main-task-processor: # Make a task processor for CPU-bound couroutine tasks. thread_name: main-worker # OS will show the threads of this task processor with 'main-worker' prefix. - worker_threads: 46 + worker_threads: 48 guess-cpu-limit: true + task-processor-queue: work-stealing-task-queue fs-task-processor: # Make a separate task processor for filesystem bound tasks. thread_name: fs-worker From 9e58d22fdf5d4a3a77c6df727d4c02d670274e19 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Mon, 26 Aug 2024 21:28:57 +0500 Subject: [PATCH 08/40] [ntex] replace async-std with compio runtime (#9222) * ntex: replace async-std with compio * wip * wip --- frameworks/Rust/ntex/Cargo.toml | 21 ++++++++++++------- frameworks/Rust/ntex/benchmark_config.json | 12 +++++------ frameworks/Rust/ntex/config.toml | 6 +++--- ...astd.dockerfile => ntex-compio.dockerfile} | 4 ++-- ...d.dockerfile => ntex-db-compio.dockerfile} | 4 ++-- ....dockerfile => ntex-plt-compio.dockerfile} | 4 ++-- frameworks/Rust/ntex/src/main.rs | 1 - frameworks/Rust/ntex/src/main_plt.rs | 2 +- 8 files changed, 30 insertions(+), 24 deletions(-) rename frameworks/Rust/ntex/{ntex-astd.dockerfile => ntex-compio.dockerfile} (84%) rename frameworks/Rust/ntex/{ntex-db-astd.dockerfile => ntex-db-compio.dockerfile} (84%) rename frameworks/Rust/ntex/{ntex-plt-astd.dockerfile => ntex-plt-compio.dockerfile} (83%) diff --git a/frameworks/Rust/ntex/Cargo.toml b/frameworks/Rust/ntex/Cargo.toml index 92c0da890ac..850e640f2ad 100755 --- a/frameworks/Rust/ntex/Cargo.toml +++ b/frameworks/Rust/ntex/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "ntex" +name = "ntex-bench" version = "2.0.0" edition = "2018" @@ -8,7 +8,7 @@ name = "ntex" path = "src/main.rs" [[bin]] -name = "ntex-astd" +name = "ntex-compio" path = "src/main.rs" [[bin]] @@ -16,7 +16,7 @@ name = "ntex-db" path = "src/main_db.rs" [[bin]] -name = "ntex-db-astd" +name = "ntex-db-compio" path = "src/main_db.rs" [[bin]] @@ -24,7 +24,7 @@ name = "ntex-plt" path = "src/main_plt.rs" [[bin]] -name = "ntex-plt-astd" +name = "ntex-plt-compio" path = "src/main_plt.rs" [features] @@ -33,11 +33,11 @@ default = [] # tokio runtime tokio = ["ntex/tokio"] -# async-std runtime -async-std = ["ntex/async-std"] +# compio runtime +compio = ["ntex/compio"] [dependencies] -ntex = "=2.1.0" +ntex = "2.4" 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"] } @@ -63,3 +63,10 @@ lto = "thin" debug = false incremental = false overflow-checks = false + +[patch.crates-io] +ntex = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" } +ntex-io = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" } +ntex-rt = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" } +ntex-net = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" } +ntex-compio = { git = "https://github.com/ntex-rs/ntex.git", branch = "compio" } diff --git a/frameworks/Rust/ntex/benchmark_config.json b/frameworks/Rust/ntex/benchmark_config.json index ab6fc091970..9ed29c64b97 100755 --- a/frameworks/Rust/ntex/benchmark_config.json +++ b/frameworks/Rust/ntex/benchmark_config.json @@ -19,7 +19,7 @@ "notes": "", "versus": "" }, - "astd": { + "compio": { "json_url": "/json", "plaintext_url": "/plaintext", "port": 8080, @@ -33,7 +33,7 @@ "webserver": "ntex", "os": "Linux", "database_os": "Linux", - "display_name": "ntex [async-std]", + "display_name": "ntex [compio]", "notes": "", "versus": "" }, @@ -57,7 +57,7 @@ "notes": "", "versus": "" }, - "db-astd": { + "db-compio": { "fortune_url": "/fortunes", "db_url": "/db", "query_url": "/query?q=", @@ -73,7 +73,7 @@ "webserver": "ntex", "os": "Linux", "database_os": "Linux", - "display_name": "ntex [async-std,db]", + "display_name": "ntex [compio,db]", "notes": "", "versus": "" }, @@ -95,7 +95,7 @@ "notes": "", "versus": "" }, - "plt-astd": { + "plt-compio": { "json_url": "/json", "plaintext_url": "/plaintext", "port": 8080, @@ -109,7 +109,7 @@ "webserver": "ntex", "os": "Linux", "database_os": "Linux", - "display_name": "ntex [async-std,platform]", + "display_name": "ntex [compio,platform]", "notes": "", "versus": "" } diff --git a/frameworks/Rust/ntex/config.toml b/frameworks/Rust/ntex/config.toml index 84527c12626..759dca26c70 100644 --- a/frameworks/Rust/ntex/config.toml +++ b/frameworks/Rust/ntex/config.toml @@ -14,7 +14,7 @@ platform = "None" webserver = "ntex" versus = "" -[astd] +[compio] urls.plaintext = "/plaintext" urls.json = "/json" approach = "Realistic" @@ -42,7 +42,7 @@ platform = "None" webserver = "ntex" versus = "" -[db-astd] +[db-compio] urls.db = "/db" urls.query = "/query?q=" urls.update = "/update?q=" @@ -70,7 +70,7 @@ platform = "None" webserver = "ntex" versus = "" -[plt-astd] +[plt-compio] urls.plaintext = "/plaintext" urls.json = "/json" approach = "Realistic" diff --git a/frameworks/Rust/ntex/ntex-astd.dockerfile b/frameworks/Rust/ntex/ntex-compio.dockerfile similarity index 84% rename from frameworks/Rust/ntex/ntex-astd.dockerfile rename to frameworks/Rust/ntex/ntex-compio.dockerfile index be97758bbeb..c825e18078e 100644 --- a/frameworks/Rust/ntex/ntex-astd.dockerfile +++ b/frameworks/Rust/ntex/ntex-compio.dockerfile @@ -9,8 +9,8 @@ ADD ./ /ntex WORKDIR /ntex RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="async-std" +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="compio" EXPOSE 8080 -CMD ./target/release/ntex-astd +CMD ./target/release/ntex-compio diff --git a/frameworks/Rust/ntex/ntex-db-astd.dockerfile b/frameworks/Rust/ntex/ntex-db-compio.dockerfile similarity index 84% rename from frameworks/Rust/ntex/ntex-db-astd.dockerfile rename to frameworks/Rust/ntex/ntex-db-compio.dockerfile index e8717d37a50..c892bcdc9fc 100644 --- a/frameworks/Rust/ntex/ntex-db-astd.dockerfile +++ b/frameworks/Rust/ntex/ntex-db-compio.dockerfile @@ -9,8 +9,8 @@ ADD ./ /ntex WORKDIR /ntex RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="async-std" +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="compio" EXPOSE 8080 -CMD ./target/release/ntex-db-astd +CMD ./target/release/ntex-db-compio diff --git a/frameworks/Rust/ntex/ntex-plt-astd.dockerfile b/frameworks/Rust/ntex/ntex-plt-compio.dockerfile similarity index 83% rename from frameworks/Rust/ntex/ntex-plt-astd.dockerfile rename to frameworks/Rust/ntex/ntex-plt-compio.dockerfile index 8ec6c7fe636..849e224994b 100644 --- a/frameworks/Rust/ntex/ntex-plt-astd.dockerfile +++ b/frameworks/Rust/ntex/ntex-plt-compio.dockerfile @@ -9,8 +9,8 @@ ADD ./ /ntex WORKDIR /ntex RUN cargo clean -RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="async-std" +RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features="compio" EXPOSE 8080 -CMD ./target/release/ntex-plt-astd +CMD ./target/release/ntex-plt-compio diff --git a/frameworks/Rust/ntex/src/main.rs b/frameworks/Rust/ntex/src/main.rs index c456fac47e4..218ed03c727 100644 --- a/frameworks/Rust/ntex/src/main.rs +++ b/frameworks/Rust/ntex/src/main.rs @@ -1,6 +1,5 @@ #[global_allocator] static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; -// static GLOBAL: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; use ntex::http::header::{CONTENT_TYPE, SERVER}; use ntex::{http, time::Seconds, util::BytesMut, util::PoolId, web}; diff --git a/frameworks/Rust/ntex/src/main_plt.rs b/frameworks/Rust/ntex/src/main_plt.rs index 2f46ce448e1..b6c435f6773 100644 --- a/frameworks/Rust/ntex/src/main_plt.rs +++ b/frameworks/Rust/ntex/src/main_plt.rs @@ -1,5 +1,5 @@ #[global_allocator] -static GLOBAL: snmalloc_rs::SnMalloc = snmalloc_rs::SnMalloc; +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; use std::{future::Future, io, pin::Pin, task::Context, task::Poll}; From 98fb99ac99759e4d8deddf6f212bb7743019b1e6 Mon Sep 17 00:00:00 2001 From: Anton Kirilov Date: Mon, 26 Aug 2024 17:29:50 +0100 Subject: [PATCH 09/40] Revert "H2O: Use 2 database connections per thread again (#9176)" (#9223) This reverts commit 57f2f117488029a625feea0605f7da76bfb2a0b9. --- frameworks/C/h2o/h2o.dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/C/h2o/h2o.dockerfile b/frameworks/C/h2o/h2o.dockerfile index 3b383b7f6df..976c938337a 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", \ - "-m2"] + "-m1"] From 12ba6b9c5a8c54b6be540feead83dce7206d3def Mon Sep 17 00:00:00 2001 From: Yan Kun <1939810907@qq.com> Date: Tue, 27 Aug 2024 00:30:06 +0800 Subject: [PATCH 10/40] [Scala/otavia] upgrade otavia to 0.4.2 (#9224) * [Scala/otavia] upgrade otavia to 0.4.2 * [Scala/otavia] change randomnumber to randomNumber * [Scala/otavia] upgrade otavia to 0.4.3 --- .../Scala/otavia/{README.MD => README.md} | 0 .../src/app/controller/DBController.scala | 19 ++++---- .../app/controller/FortuneController.scala | 18 +++++-- .../benchmark/src/app/model/Fortune.scala | 4 +- .../benchmark/src/app/model/World.scala | 4 +- .../src/app/util/FortunesRender.scala | 6 +-- frameworks/Scala/otavia/benchmark_config.json | 48 ++++++++++++++++++- frameworks/Scala/otavia/build.sc | 2 +- frameworks/Scala/otavia/config.toml | 36 +++++++++++++- .../otavia-equalization-offgc.dockerfile | 16 +++++++ ...kerfile => otavia-equalization.dockerfile} | 4 +- .../Scala/otavia/otavia-offgc.dockerfile | 16 +++++++ frameworks/Scala/otavia/otavia.dockerfile | 4 +- 13 files changed, 148 insertions(+), 29 deletions(-) rename frameworks/Scala/otavia/{README.MD => README.md} (100%) create mode 100644 frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile rename frameworks/Scala/otavia/{otavia-reserve.dockerfile => otavia-equalization.dockerfile} (76%) create mode 100644 frameworks/Scala/otavia/otavia-offgc.dockerfile diff --git a/frameworks/Scala/otavia/README.MD b/frameworks/Scala/otavia/README.md similarity index 100% rename from frameworks/Scala/otavia/README.MD rename to frameworks/Scala/otavia/README.md diff --git a/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala b/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala index 6b54504aecc..2e9e32abbe7 100644 --- a/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala +++ b/frameworks/Scala/otavia/benchmark/src/app/controller/DBController.scala @@ -9,7 +9,7 @@ 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 cc.otavia.sql.statement.{ModifyRows, PrepareQuery} import java.util.SplittableRandom @@ -22,20 +22,17 @@ class DBController extends StateActor[REQ] { 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) + stack.ask match + case _: SingleQueryRequest => handleSingleQuery(stack.asInstanceOf[AskStack[SingleQueryRequest]]) + case _: MultipleQueryRequest => handleMultipleQuery(stack.asInstanceOf[AskStack[MultipleQueryRequest]]) + case _: UpdateRequest => handleUpdateQuery(stack.asInstanceOf[AskStack[UpdateRequest]]) // 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) + connection.ask(PrepareQuery.fetchOne[World](SELECT_WORLD, randomWorld()), state.future) stack.suspend(state) case state: FutureState[World] => stack.`return`(state.future.getNow) @@ -61,7 +58,7 @@ class DBController extends StateActor[REQ] { 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) + connection.ask(PrepareQuery.updateBatch(UPDATE_WORLD, newWorlds), newState.future) stack.suspend(newState) case state: FutureState[ModifyRows] => if (state.future.isFailed) state.future.causeUnsafe.printStackTrace() @@ -72,7 +69,7 @@ class DBController extends StateActor[REQ] { 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) + connection.ask(PrepareQuery.fetchOne[World](SELECT_WORLD, randomWorld()), future) state } diff --git a/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala b/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala index 05ff8c468ba..4f7fe7bf800 100644 --- a/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala +++ b/frameworks/Scala/otavia/benchmark/src/app/controller/FortuneController.scala @@ -7,12 +7,20 @@ 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.statement.PrepareQuery import cc.otavia.sql.{Connection, RowSet} +import java.util +import java.util.Comparator + class FortuneController extends StateActor[FortuneRequest] { private var connection: Address[MessageOf[Connection]] = _ + private val tmpArray: Array[Fortune] = new Array[Fortune](13) + + private val comparator = new Comparator[Fortune] { + override def compare(o1: Fortune, o2: Fortune): Int = o1.message.compareTo(o2.message) + } override protected def afterMount(): Unit = connection = autowire[Connection]() @@ -24,8 +32,10 @@ class FortuneController extends StateActor[FortuneRequest] { 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) + System.arraycopy(state.future.getNow.rows, 0, tmpArray, 0, 12) + tmpArray(12) = Fortune(0, "Additional fortune added at request time.") + util.Arrays.sort(tmpArray, comparator) + val fortunes = tmpArray.clone() val response = HttpResponse.builder.setContent(fortunes).build() stack.`return`(response) } @@ -34,7 +44,7 @@ class FortuneController extends StateActor[FortuneRequest] { object FortuneController { - class FortuneRequest extends HttpRequest[Nothing, HttpResponse[Seq[Fortune]]] + class FortuneRequest extends HttpRequest[Nothing, HttpResponse[Array[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 index edb58d3cdc9..1df592954a4 100644 --- a/frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala +++ b/frameworks/Scala/otavia/benchmark/src/app/model/Fortune.scala @@ -1,7 +1,7 @@ package app.model import cc.otavia.json.JsonSerde -import cc.otavia.sql.{Row, RowDecoder} +import cc.otavia.sql.{Row, RowCodec} /** The model for the "fortune" database table. */ -case class Fortune(id: Int, message: String) extends Row derives RowDecoder, JsonSerde +case class Fortune(id: Int, message: String) extends Row derives RowCodec, JsonSerde diff --git a/frameworks/Scala/otavia/benchmark/src/app/model/World.scala b/frameworks/Scala/otavia/benchmark/src/app/model/World.scala index a0e6f6056f8..af6f8539d74 100644 --- a/frameworks/Scala/otavia/benchmark/src/app/model/World.scala +++ b/frameworks/Scala/otavia/benchmark/src/app/model/World.scala @@ -2,7 +2,7 @@ package app.model import cc.otavia.json.JsonSerde import cc.otavia.serde.annotation.rename -import cc.otavia.sql.{Row, RowDecoder} +import cc.otavia.sql.{Row, RowCodec} /** The model for the "world" database table. */ -case class World(id: Int, @rename("randomnumber") randomNumber: Int) extends Row derives RowDecoder, JsonSerde +case class World(id: Int, randomNumber: Int) extends Row derives RowCodec, JsonSerde diff --git a/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala b/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala index 0c0694ee836..69401305550 100644 --- a/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala +++ b/frameworks/Scala/otavia/benchmark/src/app/util/FortunesRender.scala @@ -7,7 +7,7 @@ import cc.otavia.serde.Serde import java.nio.charset.StandardCharsets import scala.annotation.switch -class FortunesRender extends Serde[Seq[Fortune]] { +class FortunesRender extends Serde[Array[Fortune]] { private val text1 = "Fortunes" @@ -27,7 +27,7 @@ class FortunesRender extends Serde[Seq[Fortune]] { private val squot = "'".getBytes() private val amp = "&".getBytes() - override def serialize(fortunes: Seq[Fortune], out: Buffer): Unit = { + override def serialize(fortunes: Array[Fortune], out: Buffer): Unit = { out.writeBytes(text1) for (fortune <- fortunes) { out.writeBytes(text2) @@ -39,7 +39,7 @@ class FortunesRender extends Serde[Seq[Fortune]] { out.writeBytes(text5) } - override def deserialize(in: Buffer): Seq[Fortune] = throw new UnsupportedOperationException() + override def deserialize(in: Buffer): Array[Fortune] = throw new UnsupportedOperationException() private def writeEscapeMessage(buffer: Buffer, message: String): Unit = { var i = 0 diff --git a/frameworks/Scala/otavia/benchmark_config.json b/frameworks/Scala/otavia/benchmark_config.json index ae712574778..a93a000f3b4 100644 --- a/frameworks/Scala/otavia/benchmark_config.json +++ b/frameworks/Scala/otavia/benchmark_config.json @@ -25,7 +25,53 @@ "notes": "", "versus": "Otavia" }, - "reserve": { + "equalization": { + "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" + }, + "equalization-offgc": { + "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" + }, + "offgc": { "json_url": "/json", "plaintext_url": "/plaintext", "db_url": "/db", diff --git a/frameworks/Scala/otavia/build.sc b/frameworks/Scala/otavia/build.sc index 2b7877b7891..7f872fdf851 100644 --- a/frameworks/Scala/otavia/build.sc +++ b/frameworks/Scala/otavia/build.sc @@ -1,7 +1,7 @@ import mill._ import mill.scalalib._ -def otaviaVersion = "0.4.0" +def otaviaVersion = "0.4.3" object benchmark extends ScalaModule { diff --git a/frameworks/Scala/otavia/config.toml b/frameworks/Scala/otavia/config.toml index 96613dfd2fd..9443c4d261b 100644 --- a/frameworks/Scala/otavia/config.toml +++ b/frameworks/Scala/otavia/config.toml @@ -18,7 +18,7 @@ platform = "Otavia" webserver = "None" versus = "Otavia" -[reserve] +[equalization] urls.plaintext = "/plaintext" urls.json = "/json" urls.db = "/db" @@ -34,3 +34,37 @@ orm = "Micro" platform = "Otavia" webserver = "None" versus = "Otavia" + +[equalization-offgc] +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" + +[offgc] +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" \ No newline at end of file diff --git a/frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile b/frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile new file mode 100644 index 00000000000..23c9a90fd9e --- /dev/null +++ b/frameworks/Scala/otavia/otavia-equalization-offgc.dockerfile @@ -0,0 +1,16 @@ +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=56 -Dcc.otavia.nio.worker.size=56 \ + -Dcc.otavia.system.gc.aggressive=false \ + -jar \ + out/benchmark/assembly.dest/out.jar \ + jdbc:postgresql://tfb-database:5432/hello_world \ + benchmarkdbuser benchmarkdbpass 56 diff --git a/frameworks/Scala/otavia/otavia-reserve.dockerfile b/frameworks/Scala/otavia/otavia-equalization.dockerfile similarity index 76% rename from frameworks/Scala/otavia/otavia-reserve.dockerfile rename to frameworks/Scala/otavia/otavia-equalization.dockerfile index 5768000706e..780aeafe0b0 100644 --- a/frameworks/Scala/otavia/otavia-reserve.dockerfile +++ b/frameworks/Scala/otavia/otavia-equalization.dockerfile @@ -8,8 +8,8 @@ RUN mill benchmark.assembly EXPOSE 8080 CMD java -server \ - -Dcc.otavia.actor.worker.size=18 -Dcc.otavia.nio.worker.size=36 \ + -Dcc.otavia.actor.worker.size=56 -Dcc.otavia.nio.worker.size=56 \ -jar \ out/benchmark/assembly.dest/out.jar \ jdbc:postgresql://tfb-database:5432/hello_world \ - benchmarkdbuser benchmarkdbpass 54 + benchmarkdbuser benchmarkdbpass 56 diff --git a/frameworks/Scala/otavia/otavia-offgc.dockerfile b/frameworks/Scala/otavia/otavia-offgc.dockerfile new file mode 100644 index 00000000000..378a48dd2f9 --- /dev/null +++ b/frameworks/Scala/otavia/otavia-offgc.dockerfile @@ -0,0 +1,16 @@ +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=28 -Dcc.otavia.nio.worker.size=56 \ + -Dcc.otavia.system.gc.aggressive=false \ + -jar \ + out/benchmark/assembly.dest/out.jar \ + jdbc:postgresql://tfb-database:5432/hello_world \ + benchmarkdbuser benchmarkdbpass 56 diff --git a/frameworks/Scala/otavia/otavia.dockerfile b/frameworks/Scala/otavia/otavia.dockerfile index c1c944d60aa..e407df7ad79 100644 --- a/frameworks/Scala/otavia/otavia.dockerfile +++ b/frameworks/Scala/otavia/otavia.dockerfile @@ -8,8 +8,8 @@ RUN mill benchmark.assembly EXPOSE 8080 CMD java -server \ - -Dcc.otavia.actor.worker.size=24 -Dcc.otavia.nio.worker.size=48 \ + -Dcc.otavia.actor.worker.size=28 -Dcc.otavia.nio.worker.size=56 \ -jar \ out/benchmark/assembly.dest/out.jar \ jdbc:postgresql://tfb-database:5432/hello_world \ - benchmarkdbuser benchmarkdbpass 72 + benchmarkdbuser benchmarkdbpass 56 From 8d455d57e1eb293f7959b93bead6102df9e19403 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 28 Aug 2024 01:58:12 +0800 Subject: [PATCH 11/40] [xitca-web] fix wasi build. (#9225) * [xitca-web] fix wasi build. * fix config json. --- frameworks/Rust/xitca-web/Cargo.lock | 60 +++++++------- frameworks/Rust/xitca-web/Cargo.toml | 3 +- .../Rust/xitca-web/benchmark_config.json | 3 +- frameworks/Rust/xitca-web/src/db.rs | 78 +++++++++++-------- frameworks/Rust/xitca-web/src/db_diesel.rs | 6 +- frameworks/Rust/xitca-web/src/main.rs | 2 +- frameworks/Rust/xitca-web/src/main_iou.rs | 3 +- frameworks/Rust/xitca-web/src/main_sync.rs | 7 +- .../Rust/xitca-web/xitca-web-wasm.dockerfile | 2 +- 9 files changed, 93 insertions(+), 71 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index e510a6c31dc..01bd80ec5e3 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -149,9 +149,12 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.8" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -161,9 +164,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -471,9 +474,9 @@ checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libmimalloc-sys" @@ -560,9 +563,8 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +version = "1.0.2" +source = "git+https://github.com/fakeshadow/mio?rev=9bae6012b7ecfc6083350785f71a5e8265358178#9bae6012b7ecfc6083350785f71a5e8265358178" dependencies = [ "hermit-abi", "libc", @@ -847,18 +849,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", @@ -867,9 +869,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.125" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" dependencies = [ "itoa", "memchr", @@ -910,6 +912,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -979,9 +987,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -1017,9 +1025,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "libc", @@ -1079,15 +1087,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -1138,9 +1146,9 @@ dependencies = [ [[package]] name = "unicode-properties" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" [[package]] name = "vcpkg" @@ -1311,7 +1319,7 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=0cad5309beb278dc967378a35b733e26be0d4073#0cad5309beb278dc967378a35b733e26be0d4073" +source = "git+https://github.com/HFQR/xitca-web.git?rev=f4e7bed#f4e7bedfb441897d1f26a6e4d8cbfada23953269" dependencies = [ "fallible-iterator", "percent-encoding", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index d9606bf2a96..e4614eb0bab 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -95,4 +95,5 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "0cad5309beb278dc967378a35b733e26be0d4073" } +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "f4e7bed" } +mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } diff --git a/frameworks/Rust/xitca-web/benchmark_config.json b/frameworks/Rust/xitca-web/benchmark_config.json index 5371bcd2551..f4c152eb729 100755 --- a/frameworks/Rust/xitca-web/benchmark_config.json +++ b/frameworks/Rust/xitca-web/benchmark_config.json @@ -62,8 +62,7 @@ "database_os": "linux", "display_name": "xitca-web [wasm]", "notes": "", - "versus": "", - "tags": ["broken"] + "versus": "" }, "axum": { "json_url": "/json", diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 755dfaacf70..aa783e29dce 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,9 +1,9 @@ -use std::{collections::HashMap, fmt::Write}; +use std::fmt::Write; +use xitca_io::bytes::BytesMut; use xitca_postgres::{ pipeline::Pipeline, statement::Statement, AsyncLendingIterator, SharedClient, }; -use xitca_unsafe_collection::no_hash::NoHashBuilder; use super::{ ser::{Fortune, Fortunes, World}, @@ -13,14 +13,16 @@ use super::{ pub struct Client { client: SharedClient, #[cfg(not(feature = "pg-sync"))] - rng: std::cell::RefCell, + shared: std::cell::RefCell, #[cfg(feature = "pg-sync")] - rng: std::sync::Mutex, + shared: std::sync::Mutex, fortune: Statement, world: Statement, - updates: HashMap, + updates: Box<[Statement]>, } +type Shared = (Rand, BytesMut); + pub async fn create() -> HandleResult { let mut client = SharedClient::new(DB_URL.to_string()).await?; @@ -30,7 +32,11 @@ pub async fn create() -> HandleResult { .prepare_cached("SELECT * FROM world WHERE id=$1", &[]) .await?; - let mut updates = HashMap::default(); + let mut updates = Vec::new(); + + // a dummy statement as placeholder of 0 index. + // avoid off by one calculation when using non zero u16 as slicing index. + updates.push(Statement::default()); for num in 1..=500u16 { let mut pl = 1; @@ -49,34 +55,36 @@ pub async fn create() -> HandleResult { q.push(')'); let st = client.prepare_cached(&q, &[]).await?; - updates.insert(num, st); + updates.push(st); } + let shared = (Rand::default(), BytesMut::new()); + Ok(Client { client, #[cfg(not(feature = "pg-sync"))] - rng: std::cell::RefCell::new(Rand::default()), + shared: std::cell::RefCell::new(shared), #[cfg(feature = "pg-sync")] - rng: std::sync::Mutex::new(Rand::default()), + shared: std::sync::Mutex::new(shared), fortune, world, - updates, + updates: updates.into_boxed_slice(), }) } impl Client { #[cfg(not(feature = "pg-sync"))] - fn borrow_rng_mut(&self) -> std::cell::RefMut<'_, Rand> { - self.rng.borrow_mut() + fn shared(&self) -> std::cell::RefMut<'_, Shared> { + self.shared.borrow_mut() } #[cfg(feature = "pg-sync")] - fn borrow_rng_mut(&self) -> std::sync::MutexGuard<'_, Rand> { - self.rng.lock().unwrap() + fn shared(&self) -> std::sync::MutexGuard<'_, Shared> { + self.shared.lock().unwrap() } pub async fn get_world(&self) -> HandleResult { - let id = self.borrow_rng_mut().gen_id(); + let id = self.shared().0.gen_id(); self.client .query_raw(&self.world, [id]) .await? @@ -87,17 +95,21 @@ impl Client { } pub async fn get_worlds(&self, num: u16) -> HandleResult> { - let mut pipe = Pipeline::new(); + let len = num as usize; + + let mut res = { + let (ref mut rng, ref mut buf) = *self.shared(); + + let mut pipe = Pipeline::<_, false>::with_capacity_from_buf(len, buf); - { - let mut rng = self.borrow_rng_mut(); (0..num).try_for_each(|_| pipe.query_raw(&self.world, [rng.gen_id()]))?; + + self.client.pipeline(pipe) } + .await?; - let mut worlds = Vec::new(); - worlds.reserve(num as usize); + let mut worlds = Vec::with_capacity(len); - let mut res = self.client.pipeline(pipe).await?; while let Some(mut item) = res.try_next().await? { while let Some(row) = item.try_next().await? { worlds.push(World::new(row.get_raw(0), row.get_raw(1))) @@ -113,27 +125,31 @@ impl Client { let mut params = Vec::new(); params.reserve(len * 3); - let mut pipe = Pipeline::new(); + let mut res = { + let (ref mut rng, ref mut buf) = *self.shared(); + + let mut pipe = Pipeline::<_, false>::with_capacity_from_buf(len + 1, buf); - { - let mut rng = self.borrow_rng_mut(); (0..num).try_for_each(|_| { let w_id = rng.gen_id(); let r_id = rng.gen_id(); params.extend([w_id, r_id]); pipe.query_raw(&self.world, [w_id]) })?; - } - params.extend_from_within(..len); - let st = self.updates.get(&num).unwrap(); - pipe.query_raw(st, ¶ms)?; + params.extend_from_within(..len); + + let st = self.updates.get(len).unwrap(); + pipe.query_raw(st, ¶ms)?; + + self.client.pipeline(pipe) + } + .await?; let mut worlds = Vec::new(); worlds.reserve(len); let mut r_ids = params.into_iter().skip(1).step_by(2); - let mut res = self.client.pipeline(pipe).await?; while let Some(mut item) = res.try_next().await? { while let Some(row) = item.try_next().await? { let r_id = r_ids.next().unwrap(); @@ -148,8 +164,8 @@ impl Client { let mut items = Vec::with_capacity(32); items.push(Fortune::new(0, "Additional fortune added at request time.")); - let mut stream = self.client.query_raw::<[i32; 0]>(&self.fortune, []).await?; - while let Some(row) = stream.try_next().await? { + let mut res = self.client.query_raw::<[i32; 0]>(&self.fortune, []).await?; + while let Some(row) = res.try_next().await? { items.push(Fortune::new(row.get_raw(0), row.get_raw::(1))); } items.sort_by(|it, next| it.message.cmp(&next.message)); diff --git a/frameworks/Rust/xitca-web/src/db_diesel.rs b/frameworks/Rust/xitca-web/src/db_diesel.rs index 49a3e158e18..79ba4c9a69a 100644 --- a/frameworks/Rust/xitca-web/src/db_diesel.rs +++ b/frameworks/Rust/xitca-web/src/db_diesel.rs @@ -16,8 +16,8 @@ pub struct _Pool { pub fn create() -> std::io::Result> { r2d2::Builder::new() - .max_size(256) - .min_idle(Some(256)) + .max_size(100) + .min_idle(Some(100)) .test_on_check_out(false) .idle_timeout(None) .max_lifetime(None) @@ -34,7 +34,7 @@ pub fn create() -> std::io::Result> { #[cold] #[inline(never)] fn not_found() -> Error { - format!("world not found").into() + "world not found".into() } impl _Pool { diff --git a/frameworks/Rust/xitca-web/src/main.rs b/frameworks/Rust/xitca-web/src/main.rs index 632504dac5e..8405c986717 100755 --- a/frameworks/Rust/xitca-web/src/main.rs +++ b/frameworks/Rust/xitca-web/src/main.rs @@ -53,7 +53,7 @@ where async fn plain_text(ctx: Ctx<'_>) -> HandleResult { let (req, _) = ctx.into_parts(); - let mut res = req.into_response(Bytes::from_static(b"Hello, World!")); + let mut res = req.into_response(const { Bytes::from_static(b"Hello, World!") }); res.headers_mut().insert(CONTENT_TYPE, TEXT); Ok(res) } diff --git a/frameworks/Rust/xitca-web/src/main_iou.rs b/frameworks/Rust/xitca-web/src/main_iou.rs index 67ae6dad4d3..8ca722f1fbe 100644 --- a/frameworks/Rust/xitca-web/src/main_iou.rs +++ b/frameworks/Rust/xitca-web/src/main_iou.rs @@ -57,8 +57,7 @@ async fn handler(ctx: Ctx<'_, Request>) -> Result { let (req, state) = ctx.into_parts(); let mut res = match req.uri().path() { "/plaintext" => { - const HELLO: Bytes = Bytes::from_static(b"Hello, World!"); - let mut res = req.into_response(HELLO); + let mut res = req.into_response(const { Bytes::from_static(b"Hello, World!") }); res.headers_mut().insert(CONTENT_TYPE, TEXT); res } diff --git a/frameworks/Rust/xitca-web/src/main_sync.rs b/frameworks/Rust/xitca-web/src/main_sync.rs index 03f6c9ea3a3..cf36166ac70 100644 --- a/frameworks/Rust/xitca-web/src/main_sync.rs +++ b/frameworks/Rust/xitca-web/src/main_sync.rs @@ -27,6 +27,7 @@ fn main() -> std::io::Result<()> { .at_typed(updates) .map(header) .serve() + .disable_vectored_write() .bind("0.0.0.0:8080")? .run() .wait() @@ -45,10 +46,8 @@ fn db(StateOwn(pool): StateOwn) -> HandleResult> { #[route("/fortunes", method = get)] fn fortunes(StateOwn(pool): StateOwn) -> HandleResult> { use sailfish::TemplateOnce; - pool.tell_fortune()? - .render_once() - .map(Html) - .map_err(Into::into) + let html = pool.tell_fortune()?.render_once()?; + Ok(Html(html)) } #[route("/queries", method = get)] diff --git a/frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile b/frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile index 51aa96fd4eb..02634638c16 100644 --- a/frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile +++ b/frameworks/Rust/xitca-web/xitca-web-wasm.dockerfile @@ -1,7 +1,7 @@ ARG WASMTIME_VERSION=15.0.0 ARG WASM_TARGET=wasm32-wasip1-threads -FROM rust:1.77 AS compile +FROM rust:1.79 AS compile ARG WASMTIME_VERSION ARG WASM_TARGET From 33044001ca026e7fb2652d5deb2cbda4d19a0358 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Wed, 28 Aug 2024 01:58:27 +0800 Subject: [PATCH 12/40] [PHP]update swoole version to 5.1.4 (#9229) * update swoole version to 5.1.4 * update container to 24.04 * cache statement for coroutine type --- frameworks/PHP/swoole/database.php | 112 ++++++++++++------ frameworks/PHP/swoole/php.ini | 2 +- .../PHP/swoole/swoole-async-mysql.dockerfile | 6 +- .../swoole/swoole-async-postgres.dockerfile | 6 +- frameworks/PHP/swoole/swoole-server.php | 14 ++- .../PHP/swoole/swoole-sync-mysql.dockerfile | 6 +- .../swoole/swoole-sync-postgres.dockerfile | 6 +- 7 files changed, 96 insertions(+), 56 deletions(-) diff --git a/frameworks/PHP/swoole/database.php b/frameworks/PHP/swoole/database.php index 6a7cdb3c1ea..19aac390968 100644 --- a/frameworks/PHP/swoole/database.php +++ b/frameworks/PHP/swoole/database.php @@ -21,14 +21,14 @@ public static function db(PDOStatement|PDOStatementProxy $db): string public static function fortunes(PDOStatement|PDOStatementProxy $fortune): string { $fortune->execute(); - $results = $fortune->fetchAll(PDO::FETCH_KEY_PAIR); + $results = $fortune->fetchAll(PDO::FETCH_KEY_PAIR); $results[0] = 'Additional fortune added at request time.'; asort($results); $html = ''; foreach ($results as $id => $message) { $message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8'); - $html .= ""; + $html .= ""; } return "Fortunes
idmessage
$id$message
$id$message
$html
idmessage
"; @@ -36,13 +36,8 @@ public static function fortunes(PDOStatement|PDOStatementProxy $fortune): string public static function query(PDOStatement|PDOStatementProxy $query, int $queries): string { - $query_count = 1; - if ($queries > 1) { - $query_count = min($queries, 500); - } - $results = []; - while ($query_count--) { + while ($queries--) { $query->execute([mt_rand(1, 10000)]); $results[] = $query->fetch(PDO::FETCH_ASSOC); } @@ -50,33 +45,38 @@ public static function query(PDOStatement|PDOStatementProxy $query, int $queries return json_encode($results, JSON_NUMERIC_CHECK); } - public static function updates(PDOStatement|PDOStatementProxy $random, PDOStatement|PDOStatementProxy $update, int $queries): string + public static function updates(PDOStatement|PDOStatementProxy $random, PDOStatement|PDOStatementProxy $update, int $queries, string $driver): string { - $query_count = 1; - if ($queries > 1) { - $query_count = min($queries, 500); - } - - $results = []; - while ($query_count--) { - $id = mt_rand(1, 10000); - $random->execute([$id]); - $item = $random->fetch(PDO::FETCH_ASSOC); - $update->execute([$item['randomNumber'] = mt_rand(1, 10000), $id]); + $results = $keys = $values = []; + while ($queries--) { + $random->execute([mt_rand(1, 10000)]); + $item = $random->fetch(PDO::FETCH_ASSOC); + $item['randomNumber'] = mt_rand(1, 10000); + $results[] = $item; - $results[] = $item; + if ($driver == 'pgsql') { + $values[] = $keys[] = $item['id']; + $values[] = $item['randomNumber']; + } else { + $update->execute([$item['randomNumber'], $item['id']]); + } } + if ($driver == 'pgsql') { + $update->execute([...$values, ...$keys]); + } return json_encode($results, JSON_NUMERIC_CHECK); } } class Connection { + private static PDO $pdo; + private static string $driver; + private static array $updates = []; private static PDOStatement $db; private static PDOStatement $fortune; private static PDOStatement $random; - private static PDOStatement $update; private static PDOStatement $query; public static function init(string $driver): void @@ -87,15 +87,16 @@ public static function init(string $driver): void "benchmarkdbpass", [ PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, - PDO::ATTR_EMULATE_PREPARES => false + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_EMULATE_PREPARES => false ] ); - self::$db = self::$random = self::$query = $pdo->prepare(Operation::WORLD_SELECT_SQL); + self::$db = self::$random = self::$query = $pdo->prepare(Operation::WORLD_SELECT_SQL); self::$fortune = $pdo->prepare(Operation::FORTUNE_SQL); - self::$update = $pdo->prepare(Operation::WORLD_UPDATE_SQL); + self::$pdo = $pdo; + self::$driver = $driver; } public static function db(): string @@ -115,13 +116,23 @@ public static function query(int $queries): string public static function updates(int $queries): string { - return Operation::updates(self::$random, self::$update, $queries); + if (!isset(self::$updates[$queries])) { + self::$updates[$queries] = self::$driver == 'pgsql' + ? self::$pdo->prepare('UPDATE World SET randomNumber = CASE id'.\str_repeat(' WHEN ?::INTEGER THEN ?::INTEGER ', $queries).'END WHERE id IN ('.\str_repeat('?::INTEGER,', $queries - 1).'?::INTEGER)') + : self::$pdo->prepare(Operation::WORLD_UPDATE_SQL); + } + + return Operation::updates(self::$random, self::$updates[$queries], $queries, self::$driver); } } class Connections { private static PDOPool $pool; + private static string $driver; + private static array $dbs = []; + private static array $fortunes = []; + private static array $updates = []; public static function init(string $driver): void { @@ -133,22 +144,22 @@ public static function init(string $driver): void ->withUsername('benchmarkdbuser') ->withPassword('benchmarkdbpass'); - self::$pool = new PDOPool($config, intval(1024 / swoole_cpu_num())); + self::$pool = new PDOPool($config, 128); + self::$driver = $driver; } public static function db(): string { - $pdo = self::get(); - $result = Operation::db($pdo->prepare(Operation::WORLD_SELECT_SQL)); + $pdo = self::get(); + $result = Operation::db(self::getStatement($pdo, 'select')); self::put($pdo); - return $result; } public static function fortunes(): string { - $pdo = self::get(); - $result = Operation::fortunes($pdo->prepare(Operation::FORTUNE_SQL)); + $pdo = self::get(); + $result = Operation::fortunes(self::getStatement($pdo, 'fortunes')); self::put($pdo); return $result; @@ -156,8 +167,8 @@ public static function fortunes(): string public static function query(int $queries): string { - $pdo = self::get(); - $result = Operation::query($pdo->prepare(Operation::WORLD_SELECT_SQL), $queries); + $pdo = self::get(); + $result = Operation::query(self::getStatement($pdo, 'select'), $queries); self::put($pdo); return $result; @@ -165,8 +176,8 @@ public static function query(int $queries): string public static function updates(int $queries): string { - $pdo = self::get(); - $result = Operation::updates($pdo->prepare(Operation::WORLD_SELECT_SQL), $pdo->prepare(Operation::WORLD_UPDATE_SQL), $queries); + $pdo = self::get(); + $result = Operation::updates(self::getStatement($pdo, 'select'), self::getStatement($pdo, 'update', $queries), $queries, self::$driver); self::put($pdo); return $result; @@ -181,4 +192,31 @@ private static function put(PDO|PDOProxy $db): void { self::$pool->put($db); } + + private static function getStatement(PDO|PDOProxy $pdo, string $type, int $queries = 0): PDOStatement|PDOStatementProxy + { + $hash = spl_object_id($pdo); + + if ('select' == $type) { + if (!isset(self::$dbs[$hash])) { + self::$dbs[$hash] = $pdo->prepare(Operation::WORLD_SELECT_SQL); + } + + return self::$dbs[$hash]; + } elseif ('fortunes' == $type) { + if (!isset(self::$fortunes[$hash])) { + self::$fortunes[$hash] = $pdo->prepare(Operation::FORTUNE_SQL); + } + + return self::$fortunes[$hash]; + } else { + if (!isset(self::$updates[$hash][$queries])) { + self::$updates[$hash][$queries] = self::$driver == 'pgsql' + ? $pdo->prepare('UPDATE World SET randomNumber = CASE id'.\str_repeat(' WHEN ?::INTEGER THEN ?::INTEGER ', $queries).'END WHERE id IN ('.\str_repeat('?::INTEGER,', $queries - 1).'?::INTEGER)') + : $pdo->prepare(Operation::WORLD_UPDATE_SQL); + } + + return self::$updates[$hash][$queries]; + } + } } diff --git a/frameworks/PHP/swoole/php.ini b/frameworks/PHP/swoole/php.ini index 99a548fe57e..082e86dedbc 100644 --- a/frameworks/PHP/swoole/php.ini +++ b/frameworks/PHP/swoole/php.ini @@ -6,4 +6,4 @@ opcache.huge_code_pages=1 memory_limit=1024M opcache.jit_buffer_size=128M -opcache.jit=tracing +opcache.jit=1225 diff --git a/frameworks/PHP/swoole/swoole-async-mysql.dockerfile b/frameworks/PHP/swoole/swoole-async-mysql.dockerfile index 9b9daf07c43..82dbe32833f 100644 --- a/frameworks/PHP/swoole/swoole-async-mysql.dockerfile +++ b/frameworks/PHP/swoole/swoole-async-mysql.dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 -ENV SWOOLE_VERSION 5.1.1 +ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 1 ENV DATABASE_DRIVER mysql @@ -10,7 +10,7 @@ RUN apt update -yqq > /dev/null \ && apt install -yqq software-properties-common > /dev/null \ && LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null \ && apt update -yqq > /dev/null \ - && apt install php8.3-cli php8.3-pdo-mysql php8.3-dev -y > /dev/null \ + && apt install libbrotli-dev php8.3-cli php8.3-pdo-mysql php8.3-dev -y > /dev/null \ && cd /tmp && curl -sSL "https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz" | tar xzf - \ && cd /tmp/swoole-src-${SWOOLE_VERSION} \ && phpize > /dev/null \ diff --git a/frameworks/PHP/swoole/swoole-async-postgres.dockerfile b/frameworks/PHP/swoole/swoole-async-postgres.dockerfile index d75390c922e..4a6b27b2bb0 100644 --- a/frameworks/PHP/swoole/swoole-async-postgres.dockerfile +++ b/frameworks/PHP/swoole/swoole-async-postgres.dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 -ENV SWOOLE_VERSION 5.1.1 +ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 1 ENV DATABASE_DRIVER pgsql @@ -10,7 +10,7 @@ RUN apt update -yqq > /dev/null \ && apt install -yqq software-properties-common > /dev/null \ && LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null \ && apt update -yqq > /dev/null \ - && apt install php8.3-cli php8.3-pdo-pgsql php8.3-dev libpq-dev -y > /dev/null \ + && apt install libbrotli-dev php8.3-cli php8.3-pdo-pgsql php8.3-dev libpq-dev -y > /dev/null \ && cd /tmp && curl -sSL "https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz" | tar xzf - \ && cd /tmp/swoole-src-${SWOOLE_VERSION} \ && phpize > /dev/null \ diff --git a/frameworks/PHP/swoole/swoole-server.php b/frameworks/PHP/swoole/swoole-server.php index 8de85f5c0a1..3794c364cb7 100644 --- a/frameworks/PHP/swoole/swoole-server.php +++ b/frameworks/PHP/swoole/swoole-server.php @@ -48,16 +48,18 @@ $res->end($connection::fortunes()); break; case '/query': + $queries = isset($req->get['queries']) ? (int) $req->get['queries'] : -1; + $query_count = $queries > 1 ? min($queries, 500) : 1; + $res->header['Content-Type'] = 'application/json'; - $res->end($connection::query( - isset($req->get['queries']) ? (int) $req->get['queries'] : -1 - )); + $res->end($connection::query($query_count)); break; case '/updates': + $queries = isset($req->get['queries']) ? (int) $req->get['queries'] : -1; + $query_count = $queries > 1 ? min($queries, 500) : 1; + $res->header['Content-Type'] = 'application/json'; - $res->end($connection::updates( - isset($req->get['queries']) ? (int) $req->get['queries'] : -1 - )); + $res->end($connection::updates($query_count)); break; default: diff --git a/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile b/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile index 4893a1aad1a..97a0e11d111 100644 --- a/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile +++ b/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 -ENV SWOOLE_VERSION 5.1.1 +ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 0 ENV DATABASE_DRIVER mysql @@ -10,7 +10,7 @@ RUN apt update -yqq > /dev/null \ && apt install -yqq software-properties-common > /dev/null \ && LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null \ && apt update -yqq > /dev/null \ - && apt install php8.3-cli php8.3-pdo-mysql php8.3-dev -y > /dev/null \ + && apt install libbrotli-dev php8.3-cli php8.3-pdo-mysql php8.3-dev -y > /dev/null \ && cd /tmp && curl -sSL "https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz" | tar xzf - \ && cd /tmp/swoole-src-${SWOOLE_VERSION} \ && phpize > /dev/null \ diff --git a/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile b/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile index 9559267ce6c..1b5a68b6169 100644 --- a/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile +++ b/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile @@ -1,6 +1,6 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 -ENV SWOOLE_VERSION 5.1.1 +ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 0 ENV DATABASE_DRIVER pgsql @@ -10,7 +10,7 @@ RUN apt update -yqq > /dev/null \ && apt install -yqq software-properties-common > /dev/null \ && LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null \ && apt update -yqq > /dev/null \ - && apt install php8.3-cli php8.3-pdo-pgsql php8.3-dev libpq-dev -y > /dev/null \ + && apt install libbrotli-dev php8.3-cli php8.3-pdo-pgsql php8.3-dev libpq-dev -y > /dev/null \ && cd /tmp && curl -sSL "https://github.com/swoole/swoole-src/archive/v${SWOOLE_VERSION}.tar.gz" | tar xzf - \ && cd /tmp/swoole-src-${SWOOLE_VERSION} \ && phpize > /dev/null \ From b356e76c8f0c3198c6111800cca88e7831e5437e Mon Sep 17 00:00:00 2001 From: Ali RajabNezhad Date: Tue, 27 Aug 2024 21:45:53 +0330 Subject: [PATCH 13/40] Update Panther Version To 4.3.1 (#9228) --- frameworks/Python/panther/README.md | 6 ++--- frameworks/Python/panther/app.py | 30 ++++++++++------------ frameworks/Python/panther/requirements.txt | 14 +++------- 3 files changed, 20 insertions(+), 30 deletions(-) diff --git a/frameworks/Python/panther/README.md b/frameworks/Python/panther/README.md index c1edfd4f5b7..f57bc888b7e 100644 --- a/frameworks/Python/panther/README.md +++ b/frameworks/Python/panther/README.md @@ -31,6 +31,6 @@ All tests are implemented in a single file ([app.py](app.py)). ## Resources -* [GitHub](https://github.com/AliRn76/Panther) -* [Documentation](https://pantherpy.github.io) -* [PyPI](https://pypi.org/project/panther) +* GitHub -> [GitHub.com/AliRn76/Panther](https://github.com/AliRn76/Panther) +* Documentation -> [PantherPy.GitHub.io](https://pantherpy.github.io) +* PyPI -> [PyPI.org/project/Panther](https://pypi.org/project/panther) diff --git a/frameworks/Python/panther/app.py b/frameworks/Python/panther/app.py index b3f712cd979..0b20d44413c 100644 --- a/frameworks/Python/panther/app.py +++ b/frameworks/Python/panther/app.py @@ -1,11 +1,12 @@ import multiprocessing -import os +from pathlib import Path from random import randint, sample import asyncpg import jinja2 from panther import Panther from panther.app import API +from panther.events import Event from panther.request import Request from panther.response import Response, PlainTextResponse, HTMLResponse @@ -18,6 +19,7 @@ pool = None +@Event.startup async def create_db_pool(): global pool pool = await asyncpg.create_pool( @@ -31,18 +33,13 @@ async def create_db_pool(): ) +@Event.shutdown async def clean_db_pool(): await pool.close() -def load_fortunes_template(): - path = os.path.join('templates', 'fortune.html') - with open(path, 'r') as template_file: - template_text = template_file.read() - return jinja2.Template(template_text) - - -fortune_template = load_fortunes_template() +with Path('templates/fortune.html').open() as f: + fortune_template = jinja2.Template(f.read()) def get_num_queries(request): @@ -99,17 +96,16 @@ async def fortunes(): @API() async def database_updates(request: Request): num_queries = get_num_queries(request) - ids = sorted(sample(range(1, 10000 + 1), num_queries)) - numbers = sorted(sample(range(1, 10000), num_queries)) - updates = list(zip(ids, numbers)) + updates = list(zip( + sample(range(1, 10000), num_queries), + sorted(sample(range(1, 10000), num_queries)) + )) - worlds = [ - {'id': row_id, 'randomNumber': number} for row_id, number in updates - ] + worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates] async with pool.acquire() as connection: statement = await connection.prepare(READ_ROW_SQL) - for row_id, _ in updates: + for _, row_id in updates: await statement.fetchval(row_id) await connection.executemany(WRITE_ROW_SQL, updates) return Response(data=worlds) @@ -129,4 +125,4 @@ async def plaintext(): 'plaintext': plaintext, } -app = Panther(__name__, configs=__name__, urls=url_routing, startup=create_db_pool, shutdown=clean_db_pool) +app = Panther(__name__, configs=__name__, urls=url_routing) diff --git a/frameworks/Python/panther/requirements.txt b/frameworks/Python/panther/requirements.txt index 4a494ed3f7a..691d573162f 100644 --- a/frameworks/Python/panther/requirements.txt +++ b/frameworks/Python/panther/requirements.txt @@ -1,11 +1,5 @@ -panther==3.2.1 - -cython==3.0.6 -jinja2==3.1.4 - +panther==4.3.1 +cython==3.0.11 asyncpg==0.29.0 - -gunicorn==22.0.0 -uvicorn==0.24.0 -uvloop==0.19.0 -httptools==0.6.1 +gunicorn==23.0.0 +uvloop==0.20.0 From 5ec9c62c84cf5125b9fc5c9ee462b09444faa246 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Wed, 28 Aug 2024 00:47:39 +0530 Subject: [PATCH 14/40] Upgrade Deno to v1.46 (#9230) * Upgrade Deno to v1.46 Uses the new `deno serve --parallel` feature * Fix --- frameworks/TypeScript/deno/deno.dockerfile | 4 ++-- frameworks/TypeScript/deno/src/main.ts | 13 +++---------- frameworks/TypeScript/deno/src/spawn.ts | 13 ------------- 3 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 frameworks/TypeScript/deno/src/spawn.ts diff --git a/frameworks/TypeScript/deno/deno.dockerfile b/frameworks/TypeScript/deno/deno.dockerfile index bd98d179541..cfb43644c10 100644 --- a/frameworks/TypeScript/deno/deno.dockerfile +++ b/frameworks/TypeScript/deno/deno.dockerfile @@ -1,4 +1,4 @@ -FROM denoland/deno:1.42.1 +FROM denoland/deno:1.46.1 EXPOSE 8080 @@ -12,4 +12,4 @@ RUN deno cache main.ts EXPOSE 8080 -CMD ["run", "-A", "--unstable-net", "spawn.ts"] +CMD ["deno", "serve", "--parallel", "--port", "8080", "--host", "0.0.0.0", "-A", "main.ts"] diff --git a/frameworks/TypeScript/deno/src/main.ts b/frameworks/TypeScript/deno/src/main.ts index 347e7f4c1a8..3e6f71506bd 100644 --- a/frameworks/TypeScript/deno/src/main.ts +++ b/frameworks/TypeScript/deno/src/main.ts @@ -1,9 +1,8 @@ const HELLO_WORLD_STR = "Hello, World!"; const options: ResponseInit = { headers: { "Server": "Deno" } }; -Deno.serve({ - reusePort: true, - handler: (req: Request) => { +export default { + fetch: (req: Request) => { const path = req.url.slice(req.url.indexOf("/", 8)); if (path == "/plaintext") { return new Response(HELLO_WORLD_STR, options); @@ -13,10 +12,4 @@ Deno.serve({ return new Response("404 Not Found", { status: 404, ...options }); } }, - onError(err) { - console.error(err); - Deno.exit(9); - }, - port: 8080, - hostname: "0.0.0.0", -}); +}; diff --git a/frameworks/TypeScript/deno/src/spawn.ts b/frameworks/TypeScript/deno/src/spawn.ts deleted file mode 100644 index cc56c4543b6..00000000000 --- a/frameworks/TypeScript/deno/src/spawn.ts +++ /dev/null @@ -1,13 +0,0 @@ -import os from "node:os"; -import process from "node:process"; - -const numCPUs = os.cpus().length; -for (let i = 0; i < numCPUs; i++) { - new Deno.Command(Deno.execPath(), { - args: ["run", "-A", "--unstable-net", "main.ts"], - stdin: "inherit", - stdout: "inherit", - stderr: "inherit", - env: { ...process.env }, - }).spawn(); -} From 1f84792e2083cfcbef7586de4c5466b9b2ca7131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E4=B8=9C?= Date: Wed, 28 Aug 2024 03:18:50 +0800 Subject: [PATCH 15/40] [Java] Update Solon Version To 2.9.1 (#9233) * Update Solon Version To 2.9.1 * Update Solon Version To 2.9.1 --- frameworks/Java/solon/pom.xml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/frameworks/Java/solon/pom.xml b/frameworks/Java/solon/pom.xml index 58e7d792301..df69e436229 100644 --- a/frameworks/Java/solon/pom.xml +++ b/frameworks/Java/solon/pom.xml @@ -9,9 +9,8 @@ UTF-8 - 11 - 11 - 2.0.0 + 11 + 2.9.1 @@ -66,11 +65,11 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.11.0 -parameters - 1.8 - 1.8 + ${java.vertsion} + ${java.vertsion} UTF-8 false @@ -79,7 +78,7 @@ org.apache.maven.plugins maven-assembly-plugin - 3.3.0 + 3.6.0 jar-with-dependencies From 8606bb835c99db9aa9d75a5d46c52f165c58e9e1 Mon Sep 17 00:00:00 2001 From: Vladimir Shchur Date: Tue, 27 Aug 2024 22:19:13 +0300 Subject: [PATCH 16/40] [F#/Oxpecker] Improved fortunes rendering (#9234) --- frameworks/FSharp/oxpecker/src/App/App.fsproj | 5 +- frameworks/FSharp/oxpecker/src/App/Program.fs | 50 ++++++++++--------- .../FSharp/oxpecker/src/App/RenderHelpers.fs | 24 +++++++++ 3 files changed, 53 insertions(+), 26 deletions(-) create mode 100644 frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs diff --git a/frameworks/FSharp/oxpecker/src/App/App.fsproj b/frameworks/FSharp/oxpecker/src/App/App.fsproj index 1b6f8b76cd3..35df8d5c493 100644 --- a/frameworks/FSharp/oxpecker/src/App/App.fsproj +++ b/frameworks/FSharp/oxpecker/src/App/App.fsproj @@ -8,12 +8,13 @@ + - - + + \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/src/App/Program.fs b/frameworks/FSharp/oxpecker/src/App/Program.fs index 09ba84b4fae..ea6bc66b911 100644 --- a/frameworks/FSharp/oxpecker/src/App/Program.fs +++ b/frameworks/FSharp/oxpecker/src/App/Program.fs @@ -7,32 +7,34 @@ open Oxpecker module HtmlViews = open Oxpecker.ViewEngine - let private fortunesHead = - head() { - title() { raw "Fortunes" } - } - - let private layout (content: HtmlElement) = - html() { - fortunesHead - body() { content } - } - - let private fortunesTableHeader = - tr() { - th() { raw "id" } - th() { raw "message" } - } + let private head, tail = + (fun (content: HtmlElement) -> + html() { + head() { + title() { "Fortunes" } + } + body() { + table() { + tr() { + th() { "id" } + th() { "message" } + } + content + } + } + } :> HtmlElement + ) |> RenderHelpers.prerender let fortunes (fortunesData: ResizeArray) = - table() { - fortunesTableHeader - for fortune in fortunesData do - tr() { - td() { raw <| string fortune.id } - td() { fortune.message } - } - } |> layout + RenderHelpers.combine head tail ( + __() { + for fortune in fortunesData do + tr() { + td() { raw <| string fortune.id } + td() { fortune.message } + } + } + ) [] module HttpHandlers = diff --git a/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs b/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs new file mode 100644 index 00000000000..003fc09d8ce --- /dev/null +++ b/frameworks/FSharp/oxpecker/src/App/RenderHelpers.fs @@ -0,0 +1,24 @@ +module RenderHelpers + + open System.Text + open Oxpecker.ViewEngine + + let prerender (view: HtmlElement -> HtmlElement) = + let sb = StringBuilder() + let mutable head = "" + let fakeHole = + { new HtmlElement with + member this.Render(sb) = + head <- sb.ToString() + sb.Clear() |> ignore } + let readyView = view fakeHole + readyView.Render(sb) + (head, sb.ToString()) + + let inline combine (head: string) (tail: string) (hole: HtmlElement) = + { new HtmlElement with + member this.Render(sb) = + sb.Append(head) |> ignore + hole.Render(sb) + sb.Append(tail) |> ignore + } \ No newline at end of file From d04efec4de37ad44cf13b453c0d2b946e2402ebd Mon Sep 17 00:00:00 2001 From: Redkale Date: Wed, 28 Aug 2024 03:19:36 +0800 Subject: [PATCH 17/40] Update jdk-23 (#9236) * Update jdk-23 * Update jdk-23 --- frameworks/Java/redkale/benchmark_config.json | 4 ++-- frameworks/Java/redkale/config.toml | 2 +- frameworks/Java/redkale/{pom-vertx.xml => pom-pgclient.xml} | 2 +- frameworks/Java/redkale/redkale-block.dockerfile | 2 +- frameworks/Java/redkale/redkale-jdbc.dockerfile | 2 +- .../{redkale-vertx.dockerfile => redkale-pgclient.dockerfile} | 4 ++-- frameworks/Java/redkale/redkale.dockerfile | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) rename frameworks/Java/redkale/{pom-vertx.xml => pom-pgclient.xml} (99%) rename frameworks/Java/redkale/{redkale-vertx.dockerfile => redkale-pgclient.dockerfile} (86%) diff --git a/frameworks/Java/redkale/benchmark_config.json b/frameworks/Java/redkale/benchmark_config.json index eb9e8d92ba2..fa84965daa3 100644 --- a/frameworks/Java/redkale/benchmark_config.json +++ b/frameworks/Java/redkale/benchmark_config.json @@ -116,7 +116,7 @@ "notes": "", "versus": "Redkale" }, - "vertx": { + "pgclient": { "db_url": "/db", "query_url": "/queries?q=", "fortune_url": "/fortunes", @@ -133,7 +133,7 @@ "webserver": "Redkale", "os": "Linux", "database_os": "Linux", - "display_name": "redkale-vertx", + "display_name": "redkale-pgclient", "notes": "", "versus": "Redkale" } diff --git a/frameworks/Java/redkale/config.toml b/frameworks/Java/redkale/config.toml index 73c0a6678e3..c2fcbb80d77 100644 --- a/frameworks/Java/redkale/config.toml +++ b/frameworks/Java/redkale/config.toml @@ -85,7 +85,7 @@ platform = "Redkale" webserver = "Redkale" versus = "Redkale" -[vertx] +[pgclient] urls.db = "/db" urls.fortune = "/fortunes" urls.query = "/queries?q=" diff --git a/frameworks/Java/redkale/pom-vertx.xml b/frameworks/Java/redkale/pom-pgclient.xml similarity index 99% rename from frameworks/Java/redkale/pom-vertx.xml rename to frameworks/Java/redkale/pom-pgclient.xml index fc371f67798..1e7315a9ff2 100644 --- a/frameworks/Java/redkale/pom-vertx.xml +++ b/frameworks/Java/redkale/pom-pgclient.xml @@ -9,7 +9,7 @@ org.redkale.boot.Application 2.9.0-SNAPSHOT 1.3.0-SNAPSHOT - 4.5.0 + 4.5.8 2.1 UTF-8 18 diff --git a/frameworks/Java/redkale/redkale-block.dockerfile b/frameworks/Java/redkale/redkale-block.dockerfile index 67594021962..36d75c9db4d 100644 --- a/frameworks/Java/redkale/redkale-block.dockerfile +++ b/frameworks/Java/redkale/redkale-block.dockerfile @@ -6,7 +6,7 @@ COPY pom.xml pom.xml COPY BenchmarkService.java src/main/java/org/redkalex/benchmark/BenchmarkService.java RUN mvn package -q -FROM openjdk:21-jdk-slim +FROM openjdk:23-jdk-slim WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar diff --git a/frameworks/Java/redkale/redkale-jdbc.dockerfile b/frameworks/Java/redkale/redkale-jdbc.dockerfile index c6549abfa03..4588baf43f1 100644 --- a/frameworks/Java/redkale/redkale-jdbc.dockerfile +++ b/frameworks/Java/redkale/redkale-jdbc.dockerfile @@ -6,7 +6,7 @@ COPY pom-jdbc.xml pom.xml COPY BenchmarkService.java src/main/java/org/redkalex/benchmark/BenchmarkService.java RUN mvn package -q -FROM openjdk:21-jdk-slim +FROM openjdk:23-jdk-slim WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar diff --git a/frameworks/Java/redkale/redkale-vertx.dockerfile b/frameworks/Java/redkale/redkale-pgclient.dockerfile similarity index 86% rename from frameworks/Java/redkale/redkale-vertx.dockerfile rename to frameworks/Java/redkale/redkale-pgclient.dockerfile index f4099b6a776..fdc4786a478 100644 --- a/frameworks/Java/redkale/redkale-vertx.dockerfile +++ b/frameworks/Java/redkale/redkale-pgclient.dockerfile @@ -2,10 +2,10 @@ FROM maven:3.8.6-openjdk-18-slim as maven WORKDIR /redkale COPY src src COPY conf conf -COPY pom-vertx.xml pom.xml +COPY pom-pgclient.xml pom.xml RUN mvn package -q -FROM openjdk:21-jdk-slim +FROM openjdk:23-jdk-slim WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar diff --git a/frameworks/Java/redkale/redkale.dockerfile b/frameworks/Java/redkale/redkale.dockerfile index d7878808a4b..8982ae3b16d 100644 --- a/frameworks/Java/redkale/redkale.dockerfile +++ b/frameworks/Java/redkale/redkale.dockerfile @@ -5,7 +5,7 @@ COPY conf conf COPY pom.xml pom.xml RUN mvn package -q -FROM openjdk:21-jdk-slim +FROM openjdk:23-jdk-slim WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar From 48de47f8d36b1fa734bb52dbde92b78760becb3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Aug 2024 18:37:57 +0000 Subject: [PATCH 18/40] Bump com.mysql:mysql-connector-j in /frameworks/Kotlin/kooby Bumps [com.mysql:mysql-connector-j](https://github.com/mysql/mysql-connector-j) from 8.0.33 to 8.2.0. - [Changelog](https://github.com/mysql/mysql-connector-j/blob/release/9.x/CHANGES) - [Commits](https://github.com/mysql/mysql-connector-j/compare/8.0.33...8.2.0) --- updated-dependencies: - dependency-name: com.mysql:mysql-connector-j dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/Kotlin/kooby/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/Kotlin/kooby/pom.xml b/frameworks/Kotlin/kooby/pom.xml index 44397e8f522..9ae92257022 100644 --- a/frameworks/Kotlin/kooby/pom.xml +++ b/frameworks/Kotlin/kooby/pom.xml @@ -52,7 +52,7 @@ com.mysql mysql-connector-j - 8.0.33 + 8.2.0 From b8c31e25bcf99f3e20e832aa46c386ea2751fbbf Mon Sep 17 00:00:00 2001 From: Denis Stepanov Date: Fri, 30 Aug 2024 16:28:11 +0200 Subject: [PATCH 19/40] Micronaut 4.6 (#9244) * Micronaut 4.6 * Use GraalVM 21 --- frameworks/Java/micronaut/buildSrc/build.gradle | 2 +- frameworks/Java/micronaut/gradle.properties | 2 +- .../Java/micronaut/gradle/wrapper/gradle-wrapper.properties | 2 +- .../Java/micronaut/micronaut-data-jdbc-graalvm.dockerfile | 5 ++--- .../micronaut/micronaut-data-mongodb-graalvm.dockerfile | 5 ++--- .../Java/micronaut/micronaut-data-r2dbc-graalvm.dockerfile | 5 ++--- frameworks/Java/micronaut/micronaut-graalvm.dockerfile | 6 ++---- frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile | 5 ++--- .../Java/micronaut/micronaut-r2dbc-graalvm.dockerfile | 5 ++--- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/frameworks/Java/micronaut/buildSrc/build.gradle b/frameworks/Java/micronaut/buildSrc/build.gradle index 7f10f90ed59..386638337fe 100644 --- a/frameworks/Java/micronaut/buildSrc/build.gradle +++ b/frameworks/Java/micronaut/buildSrc/build.gradle @@ -8,6 +8,6 @@ repositories { } dependencies { - implementation "io.micronaut.gradle:micronaut-gradle-plugin:4.3.7" + implementation "io.micronaut.gradle:micronaut-gradle-plugin:4.4.2" implementation "com.github.johnrengelman.shadow:com.github.johnrengelman.shadow.gradle.plugin:8.1.1" } \ No newline at end of file diff --git a/frameworks/Java/micronaut/gradle.properties b/frameworks/Java/micronaut/gradle.properties index ba63eab22c9..22d843f7643 100644 --- a/frameworks/Java/micronaut/gradle.properties +++ b/frameworks/Java/micronaut/gradle.properties @@ -1 +1 @@ -micronautVersion=4.5.0 +micronautVersion=4.6.0 diff --git a/frameworks/Java/micronaut/gradle/wrapper/gradle-wrapper.properties b/frameworks/Java/micronaut/gradle/wrapper/gradle-wrapper.properties index b82aa23a4f0..9355b415575 100644 --- a/frameworks/Java/micronaut/gradle/wrapper/gradle-wrapper.properties +++ b/frameworks/Java/micronaut/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/frameworks/Java/micronaut/micronaut-data-jdbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-data-jdbc-graalvm.dockerfile index 63eb26907b0..8d7377b166d 100644 --- a/frameworks/Java/micronaut/micronaut-data-jdbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-data-jdbc-graalvm.dockerfile @@ -1,12 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-data-jdbc:nativeCompile -x test -x internalStartTestResourcesService --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-data-jdbc/build/native/nativeCompile/micronaut-data-jdbc micronaut +RUN mv /home/gradle/src/micronaut-data-jdbc/build/native/nativeCompile/micronaut-data-jdbc micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark diff --git a/frameworks/Java/micronaut/micronaut-data-mongodb-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-data-mongodb-graalvm.dockerfile index 85472860d78..f0b28e5bcf3 100644 --- a/frameworks/Java/micronaut/micronaut-data-mongodb-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-data-mongodb-graalvm.dockerfile @@ -1,12 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-data-mongodb:nativeCompile -x test -x internalStartTestResourcesService --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-data-mongodb/build/native/nativeCompile/micronaut-data-mongodb micronaut +RUN mv /home/gradle/src/micronaut-data-mongodb/build/native/nativeCompile/micronaut-data-mongodb micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark diff --git a/frameworks/Java/micronaut/micronaut-data-r2dbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-data-r2dbc-graalvm.dockerfile index 6ada77518a5..614967b3379 100644 --- a/frameworks/Java/micronaut/micronaut-data-r2dbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-data-r2dbc-graalvm.dockerfile @@ -1,12 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-data-r2dbc:nativeCompile -x test -x internalStartTestResourcesService --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-data-r2dbc/build/native/nativeCompile/micronaut-data-r2dbc micronaut +RUN mv /home/gradle/src/micronaut-data-r2dbc/build/native/nativeCompile/micronaut-data-r2dbc micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark diff --git a/frameworks/Java/micronaut/micronaut-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-graalvm.dockerfile index 6a9208967cc..0b45b87f1dc 100644 --- a/frameworks/Java/micronaut/micronaut-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-graalvm.dockerfile @@ -1,13 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-vertx-pg-client:nativeCompile -x test -x internalStartTestResourcesService --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest -RUN apk --no-cache update && apk add libstdc++ WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-vertx-pg-client/build/native/nativeCompile/micronaut-vertx-pg-client micronaut +RUN mv /home/gradle/src/micronaut-vertx-pg-client/build/native/nativeCompile/micronaut-vertx-pg-client micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark diff --git a/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile index 27cb088bb04..ceae0bdf03e 100644 --- a/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile @@ -1,12 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-jdbc:nativeCompile -x test -x internalStartTestResourcesService --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-jdbc/build/native/nativeCompile/micronaut-jdbc micronaut +RUN mv /home/gradle/src/micronaut-jdbc/build/native/nativeCompile/micronaut-jdbc micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark diff --git a/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile index ff10709dae7..574496a0b91 100644 --- a/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile @@ -1,12 +1,11 @@ -FROM ghcr.io/graalvm/native-image-community:21-ol9 as build +FROM container-registry.oracle.com/graalvm/native-image:21 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src RUN ./gradlew micronaut-r2dbc:nativeCompile -x test --no-daemon -FROM cgr.dev/chainguard/wolfi-base:latest WORKDIR /micronaut -COPY --from=build /home/gradle/src/micronaut-r2dbc/build/native/nativeCompile/micronaut-r2dbc micronaut +RUN mv /home/gradle/src/micronaut-r2dbc/build/native/nativeCompile/micronaut-r2dbc micronaut EXPOSE 8080 ENV MICRONAUT_ENVIRONMENTS=benchmark From 44a869e49fa0126831df30844ce4e897e4830264 Mon Sep 17 00:00:00 2001 From: Andrew James <59655451+andrew-james-dev@users.noreply.github.com> Date: Tue, 3 Sep 2024 20:47:27 +0100 Subject: [PATCH 20/40] feat: upgrade axum & dependencies, refactor, and add code and build optimisations (#9237) --- frameworks/Rust/axum/Cargo.lock | 1436 ++++++++++------- frameworks/Rust/axum/Cargo.toml | 75 +- frameworks/Rust/axum/README.md | 70 +- .../Rust/axum/axum-mongo-raw.dockerfile | 25 - frameworks/Rust/axum/axum-mongo.dockerfile | 25 - frameworks/Rust/axum/axum-pg-pool.dockerfile | 24 - frameworks/Rust/axum/axum-pg.dockerfile | 23 - frameworks/Rust/axum/axum-sqlx.dockerfile | 26 - frameworks/Rust/axum/axum.dockerfile | 27 +- frameworks/Rust/axum/benchmark_config.json | 13 + frameworks/Rust/axum/config.toml | 3 +- frameworks/Rust/axum/src/common/mod.rs | 51 + .../src/{models_mongo.rs => common/models.rs} | 5 + frameworks/Rust/axum/src/common/simd_json.rs | 152 ++ .../Rust/axum/src/{ => common}/utils.rs | 24 +- frameworks/Rust/axum/src/database_pg.rs | 199 --- frameworks/Rust/axum/src/database_sqlx.rs | 86 - frameworks/Rust/axum/src/main.rs | 42 +- frameworks/Rust/axum/src/main_mongo.rs | 76 +- frameworks/Rust/axum/src/main_mongo_raw.rs | 80 +- frameworks/Rust/axum/src/main_pg.rs | 90 +- frameworks/Rust/axum/src/main_pg_pool.rs | 136 +- frameworks/Rust/axum/src/main_sqlx.rs | 143 +- frameworks/Rust/axum/src/models_common.rs | 6 - .../{database_mongo.rs => mongo/database.rs} | 3 +- frameworks/Rust/axum/src/mongo/mod.rs | 1 + .../database.rs} | 3 +- frameworks/Rust/axum/src/mongo_raw/mod.rs | 1 + frameworks/Rust/axum/src/pg/database.rs | 155 ++ frameworks/Rust/axum/src/pg/mod.rs | 2 + .../axum/src/{models_pg.rs => pg/models.rs} | 0 .../database.rs} | 56 +- frameworks/Rust/axum/src/pg_pool/mod.rs | 2 + .../{models_pg_pool.rs => pg_pool/models.rs} | 0 frameworks/Rust/axum/src/server.rs | 119 +- frameworks/Rust/axum/src/sqlx/database.rs | 36 + frameworks/Rust/axum/src/sqlx/mod.rs | 2 + .../src/{models_sqlx.rs => sqlx/models.rs} | 0 38 files changed, 1741 insertions(+), 1476 deletions(-) delete mode 100644 frameworks/Rust/axum/axum-mongo-raw.dockerfile delete mode 100644 frameworks/Rust/axum/axum-mongo.dockerfile delete mode 100644 frameworks/Rust/axum/axum-pg-pool.dockerfile delete mode 100644 frameworks/Rust/axum/axum-pg.dockerfile delete mode 100644 frameworks/Rust/axum/axum-sqlx.dockerfile create mode 100644 frameworks/Rust/axum/src/common/mod.rs rename frameworks/Rust/axum/src/{models_mongo.rs => common/models.rs} (85%) create mode 100644 frameworks/Rust/axum/src/common/simd_json.rs rename frameworks/Rust/axum/src/{ => common}/utils.rs (65%) delete mode 100644 frameworks/Rust/axum/src/database_pg.rs delete mode 100644 frameworks/Rust/axum/src/database_sqlx.rs delete mode 100644 frameworks/Rust/axum/src/models_common.rs rename frameworks/Rust/axum/src/{database_mongo.rs => mongo/database.rs} (97%) create mode 100644 frameworks/Rust/axum/src/mongo/mod.rs rename frameworks/Rust/axum/src/{database_mongo_raw.rs => mongo_raw/database.rs} (97%) create mode 100644 frameworks/Rust/axum/src/mongo_raw/mod.rs create mode 100644 frameworks/Rust/axum/src/pg/database.rs create mode 100644 frameworks/Rust/axum/src/pg/mod.rs rename frameworks/Rust/axum/src/{models_pg.rs => pg/models.rs} (100%) rename frameworks/Rust/axum/src/{database_pg_pool.rs => pg_pool/database.rs} (60%) create mode 100644 frameworks/Rust/axum/src/pg_pool/mod.rs rename frameworks/Rust/axum/src/{models_pg_pool.rs => pg_pool/models.rs} (100%) create mode 100644 frameworks/Rust/axum/src/sqlx/database.rs create mode 100644 frameworks/Rust/axum/src/sqlx/mod.rs rename frameworks/Rust/axum/src/{models_sqlx.rs => sqlx/models.rs} (100%) diff --git a/frameworks/Rust/axum/Cargo.lock b/frameworks/Rust/axum/Cargo.lock index 3a9dba5fb18..005a10fb7ca 100644 --- a/frameworks/Rust/axum/Cargo.lock +++ b/frameworks/Rust/axum/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -17,11 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -32,18 +38,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -70,15 +76,26 @@ dependencies = [ "yansi-term", ] +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.3.1", + "event-listener-strategy", + "pin-project-lite", +] + [[package]] name = "async-trait" -version = "0.1.75" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] @@ -91,61 +108,32 @@ dependencies = [ ] [[package]] -name = "atomic-write-file" -version = "0.1.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.2.0" -dependencies = [ - "axum 0.6.20", - "deadpool", - "deadpool-postgres", - "dotenv", - "futures", - "futures-util", - "hyper", - "mongodb", - "num_cpus", - "rand", - "serde", - "serde_json", - "sqlx", - "tokio", - "tokio-pg-mapper", - "tokio-pg-mapper-derive", - "tokio-postgres", - "tower", - "tower-http", - "yarte", -] - -[[package]] -name = "axum" -version = "0.6.20" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", "bytes", "futures-util", "http", "http-body", + "http-body-util", "hyper", + "hyper-util", "itoa", "matchit", "memchr", @@ -157,41 +145,78 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", - "tower", + "tower 0.4.13", "tower-layer", "tower-service", ] [[package]] name = "axum-core" -version = "0.3.4" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", "futures-util", "http", "http-body", + "http-body-util", "mime", + "pin-project-lite", "rustversion", + "sync_wrapper 0.1.2", "tower-layer", "tower-service", ] +[[package]] +name = "axum-techempower" +version = "0.2.1" +dependencies = [ + "axum", + "axum-core", + "bytes", + "deadpool", + "deadpool-postgres", + "dotenv", + "futures", + "futures-util", + "hyper", + "hyper-util", + "mime", + "moka", + "mongodb", + "num_cpus", + "rand", + "serde", + "serde_json", + "serde_path_to_error", + "simd-json", + "socket2 0.5.7", + "sqlx", + "tokio", + "tokio-pg-mapper", + "tokio-pg-mapper-derive", + "tokio-postgres", + "tower 0.5.0", + "tower-http", + "yarte", +] + [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -204,9 +229,15 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -222,9 +253,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -252,15 +283,15 @@ dependencies = [ [[package]] name = "bson" -version = "2.8.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c18b51216e1f74b9d769cead6ace2f82b965b807e3d73330aabe9faec31c84" +checksum = "d8a88e82b9106923b5c4d6edfca9e7db958d4e98a478ec115022e81b9b38e2c8" dependencies = [ "ahash", "base64 0.13.1", "bitvec", "hex", - "indexmap 1.9.3", + "indexmap", "js-sys", "once_cell", "rand", @@ -273,9 +304,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -285,18 +316,19 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.83" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -307,14 +339,23 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", - "windows-targets 0.48.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", ] [[package]] @@ -329,36 +370,26 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -371,32 +402,46 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] -name = "crossbeam-queue" -version = "0.3.9" +name = "crossbeam-channel" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9bcf5bdbfdd6030fb4a1c497b5d5fc5921aa2f60d359a17e249c0e6df3de153" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] -name = "crossbeam-utils" -version = "0.8.17" +name = "crossbeam-epoch" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if", + "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crypto-common" version = "0.1.6" @@ -444,17 +489,16 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "deadpool" -version = "0.10.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb84100978c1c7b37f09ed3ce3e5f843af02c2a2c431bae5b19230dad2c1b490" +checksum = "6541a3916932fe57768d4be0b1ffb5ec7cbf74ca8c903fdfd5c0fe8aa958f0ed" dependencies = [ - "async-trait", "deadpool-runtime", "num_cpus", "serde", @@ -463,11 +507,14 @@ dependencies = [ [[package]] name = "deadpool-postgres" -version = "0.12.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda39fa1cfff190d8924d447ad04fd22772c250438ca5ce1dfb3c80621c05aaa" +checksum = "1ab8a4ea925ce79678034870834602a2980f4b88c09e97feb266496dbb4493d2" dependencies = [ + "async-trait", "deadpool", + "getrandom", + "serde", "tokio", "tokio-postgres", "tracing", @@ -475,18 +522,18 @@ dependencies = [ [[package]] name = "deadpool-runtime" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63dfa964fe2a66f3fde91fc70b267fe193d822c7e603e2a675a49a7f46ad3f49" +checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" dependencies = [ "tokio", ] [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -495,9 +542,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] @@ -515,15 +562,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 1.0.109", + "syn 2.0.75", ] [[package]] @@ -558,9 +605,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" dependencies = [ "serde", ] @@ -585,9 +632,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -610,6 +657,27 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "event-listener" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener 5.3.1", + "pin-project-lite", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -618,24 +686,27 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] -name = "finl_unicode" -version = "1.2.0" +name = "flate2" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "9c0596c1eac1f9e04ed902702e9878208b336edc9d6fddc8a48387349bab3666" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] [[package]] -name = "flate2" -version = "1.0.28" +name = "float-cmp" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ - "crc32fast", - "miniz_oxide", + "num-traits", ] [[package]] @@ -646,7 +717,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -655,21 +726,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -687,9 +743,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -702,9 +758,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -712,15 +768,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -740,38 +796,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -797,32 +853,57 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] -name = "hashbrown" -version = "0.12.3" +name = "h2" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "halfbrown" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8588661a8607108a5ca69cab034063441a0413a0b041c13618a7dd348021ef6f" +dependencies = [ + "hashbrown", + "serde", +] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -834,7 +915,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -848,9 +929,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -898,9 +979,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -909,26 +990,32 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", - "pin-project-lite", ] [[package]] -name = "http-range-header" -version = "0.3.1" +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -938,32 +1025,44 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2 0.5.5", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", "tokio", - "tower-service", - "tracing", - "want", ] [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1011,22 +1110,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.1.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" dependencies = [ "equivalent", - "hashbrown 0.14.3", + "hashbrown", ] [[package]] @@ -1035,7 +1124,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2 0.5.5", + "socket2 0.5.7", "widestring", "windows-sys 0.48.0", "winreg", @@ -1047,53 +1136,108 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "itertools" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" -dependencies = [ - "either", -] - [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" dependencies = [ - "spin 0.5.2", + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", ] [[package]] name = "libc" -version = "0.2.151" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -1120,15 +1264,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1136,9 +1280,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru-cache" @@ -1179,9 +1323,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -1197,29 +1341,63 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "0.8.10" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "moka" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" +dependencies = [ + "async-lock", + "async-trait", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "event-listener 5.3.1", + "futures-util", + "once_cell", + "parking_lot", + "quanta", + "rustc_version 0.4.0", + "smallvec", + "tagptr", + "thiserror", + "triomphe", + "uuid", ] [[package]] name = "mongodb" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c30763a5c6c52079602be44fa360ca3bfacee55fca73f4734aecd23706a7f2" +checksum = "ef206acb1b72389b49bc9985efe7eb1f8a9bb18e5680d262fac26c07f44025f1" dependencies = [ "async-trait", "base64 0.13.1", @@ -1249,49 +1427,20 @@ dependencies = [ "sha-1", "sha2", "snap", - "socket2 0.4.10", - "stringprep", - "strsim", - "take_mut", - "thiserror", - "tokio", - "tokio-rustls", - "tokio-util", - "trust-dns-proto", - "trust-dns-resolver", - "typed-builder", - "uuid", - "webpki-roots", - "zstd", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "libc", + "socket2 0.4.10", + "stringprep", + "strsim", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls", + "tokio-util", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid", + "webpki-roots", + "zstd", ] [[package]] @@ -1321,21 +1470,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -1344,9 +1498,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -1364,9 +1518,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.36.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" dependencies = [ "memchr", ] @@ -1378,54 +1532,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "openssl" -version = "0.10.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" -dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.42", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.103" +name = "parking" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1433,22 +1549,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pbkdf2" @@ -1494,29 +1610,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1547,17 +1663,17 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "postgres-protocol" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" +checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" dependencies = [ - "base64 0.21.5", + "base64 0.22.1", "byteorder", "bytes", "fallible-iterator", @@ -1571,9 +1687,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" +checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9" dependencies = [ "bytes", "fallible-iterator", @@ -1588,9 +1704,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" @@ -1604,13 +1723,28 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -1619,9 +1753,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1662,6 +1796,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "raw-cpuid" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1671,11 +1814,40 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.75", +] + [[package]] name = "regex" -version = "1.10.2" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1685,9 +1857,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1696,9 +1868,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "resolv-conf" @@ -1712,16 +1884,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1746,9 +1919,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" @@ -1765,7 +1938,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver 1.0.23", ] [[package]] @@ -1780,11 +1953,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1793,9 +1966,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring", @@ -1809,7 +1982,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -1824,24 +1997,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "schannel" -version = "0.1.22" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys 0.48.0", -] +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "scopeguard" @@ -1859,29 +2023,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.9.0" @@ -1893,9 +2034,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "semver-parser" @@ -1905,50 +2046,51 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ - "indexmap 2.1.0", + "indexmap", "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_path_to_error" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" dependencies = [ "itoa", "serde", @@ -2021,11 +2163,17 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -2040,6 +2188,28 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simd-json" +version = "0.13.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "570c430b3d902ea083097e853263ae782dfe40857d93db019a12356c8e8143fa" +dependencies = [ + "getrandom", + "halfbrown", + "lexical-core", + "ref-cast", + "serde", + "serde_json", + "simdutf8", + "value-trait", +] + +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "siphasher" version = "0.3.11" @@ -2057,9 +2227,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snap" @@ -2079,20 +2249,14 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -2114,20 +2278,19 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2138,9 +2301,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ "ahash", "atoi", @@ -2148,9 +2311,8 @@ dependencies = [ "bytes", "crc", "crossbeam-queue", - "dotenvy", "either", - "event-listener", + "event-listener 2.5.3", "futures-channel", "futures-core", "futures-intrusive", @@ -2158,13 +2320,14 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap 2.1.0", + "indexmap", "log", "memchr", - "native-tls", "once_cell", "paste", "percent-encoding", + "rustls", + "rustls-pemfile", "serde", "serde_json", "sha2", @@ -2175,13 +2338,14 @@ dependencies = [ "tokio-stream", "tracing", "url", + "webpki-roots", ] [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" dependencies = [ "proc-macro2", "quote", @@ -2192,11 +2356,10 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ - "atomic-write-file", "dotenvy", "either", "heck", @@ -2219,13 +2382,13 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", - "base64 0.21.5", - "bitflags 2.4.1", + "base64 0.21.7", + "bitflags 2.6.0", "byteorder", "bytes", "crc", @@ -2261,13 +2424,13 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", - "base64 0.21.5", - "bitflags 2.4.1", + "base64 0.21.7", + "bitflags 2.6.0", "byteorder", "crc", "dotenvy", @@ -2288,7 +2451,6 @@ dependencies = [ "rand", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", @@ -2300,9 +2462,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", "flume", @@ -2321,15 +2483,21 @@ dependencies = [ "urlencoding", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] @@ -2340,9 +2508,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2357,9 +2525,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.42" +version = "2.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" dependencies = [ "proc-macro2", "quote", @@ -2372,6 +2540,18 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + [[package]] name = "take_mut" version = "0.2.2" @@ -2386,45 +2566,46 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] name = "time" -version = "0.3.31" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -2439,18 +2620,19 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -2463,32 +2645,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2 0.5.7", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] @@ -2513,9 +2694,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" +checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3" dependencies = [ "async-trait", "byteorder", @@ -2531,7 +2712,7 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand", - "socket2 0.5.5", + "socket2 0.5.7", "tokio", "tokio-util", "whoami", @@ -2549,9 +2730,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -2560,9 +2741,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", @@ -2570,7 +2751,6 @@ dependencies = [ "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] @@ -2595,22 +2775,33 @@ dependencies = [ "tokio", "tower-layer", "tower-service", - "tracing", ] [[package]] -name = "tower-http" -version = "0.4.4" +name = "tower" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140" +checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7" dependencies = [ - "bitflags 2.4.1", - "bytes", "futures-core", "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags 2.6.0", + "bytes", "http", "http-body", - "http-range-header", + "http-body-util", "pin-project-lite", "tower-layer", "tower-service", @@ -2618,15 +2809,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" @@ -2648,7 +2839,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] @@ -2660,6 +2851,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "triomphe" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" + [[package]] name = "trust-dns-proto" version = "0.21.2" @@ -2705,12 +2902,6 @@ dependencies = [ "trust-dns-proto", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "typed-builder" version = "0.10.0" @@ -2730,9 +2921,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2742,30 +2933,36 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "unicode_categories" @@ -2781,9 +2978,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", @@ -2798,9 +2995,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", "serde", @@ -2822,6 +3019,18 @@ version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" +[[package]] +name = "value-trait" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad8db98c1e677797df21ba03fca7d3bf9bec3ca38db930954e4fe6e1ea27eb4" +dependencies = [ + "float-cmp", + "halfbrown", + "itoa", + "ryu", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -2830,18 +3039,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -2857,34 +3057,35 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2892,28 +3093,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" dependencies = [ "js-sys", "wasm-bindgen", @@ -2921,9 +3122,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "whoami" @@ -2931,16 +3132,16 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall", + "redox_syscall 0.4.1", "wasite", "web-sys", ] [[package]] name = "widestring" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" [[package]] name = "winapi" @@ -2966,11 +3167,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2988,7 +3189,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3008,17 +3218,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3029,9 +3240,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3041,9 +3252,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3053,9 +3264,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3065,9 +3282,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3077,9 +3294,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3089,9 +3306,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3101,9 +3318,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winreg" @@ -3220,29 +3437,30 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.75", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" [[package]] name = "zstd" @@ -3265,9 +3483,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" +version = "2.0.13+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" dependencies = [ "cc", "pkg-config", diff --git a/frameworks/Rust/axum/Cargo.toml b/frameworks/Rust/axum/Cargo.toml index f4ecf45adf4..49b594972d1 100644 --- a/frameworks/Rust/axum/Cargo.toml +++ b/frameworks/Rust/axum/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "axum" -version = "0.2.0" +name = "axum-techempower" +version = "0.2.1" authors = ["Dragos Varovici "] edition = "2021" @@ -28,28 +28,63 @@ path = "src/main_mongo_raw.rs" name = "axum-pg" path = "src/main_pg.rs" +[features] +default = [] +simd-json = [ + "dep:simd-json", + "dep:axum-core", + "dep:mime", + "dep:bytes", + "dep:serde_path_to_error", +] + [dependencies] -axum = { version = "0.6.16", default-features = false, features = ["json", "query", "http1", "tokio"] } -deadpool = { version = "0.10.0", features = ["rt_tokio_1", "serde", "async-trait", "managed" ] } -deadpool-postgres = "0.12.1" +axum = { version = "0.7.5", default-features = false, features = [ + "json", + "query", + "http1", + "tokio", +] } +deadpool = { version = "0.12.1", features = ["rt_tokio_1", "serde", "managed"] } +deadpool-postgres = { version = "0.14.0", features = ["rt_tokio_1", "serde"] } dotenv = "0.15.0" -futures = "0.3.25" -futures-util = "0.3.25" -hyper = { version = "0.14.23", features = ["http1", "server"] } -mongodb = { version = "2.3.1", features = ["zstd-compression", "snappy-compression", "zlib-compression"] } -num_cpus = "1.14.0" +futures = "0.3.30" +futures-util = "0.3.30" +mongodb = { version = "2.8.0", features = [ + "zstd-compression", + "snappy-compression", + "zlib-compression", +] } +num_cpus = "1.16.0" rand = { version = "0.8.5", features = ["small_rng"] } -serde = { version = "1.0.149", features = ["derive"] } -serde_json = "1.0.89" -sqlx = { version = "0.7.3", features = ["postgres", "macros", "runtime-tokio-native-tls"] } -tokio = { version = "1.24.2", features = ["full"] } -tokio-pg-mapper = "0.2.0" -tokio-pg-mapper-derive = "0.2.0" -tokio-postgres = "0.7.7" -tower = { version = "0.4.13", features = ["util"] } -tower-http = { version = "0.4.0", features = ["set-header"] } +serde = { version = "1.0.196", features = ["derive"] } +serde_json = "1.0.127" +sqlx = { version = "0.7.3", features = [ + "postgres", + "macros", + "runtime-tokio", + "tls-rustls", +] } +tokio = { version = "1.39.3", features = ["full"] } +tokio-pg-mapper = { version = "0.2.0" } +tokio-pg-mapper-derive = { version = "0.2.0" } +tokio-postgres = { version = "0.7.11" } +tower = { version = "0.5.0", features = ["util"] } +tower-http = { version = "0.5.2", features = ["set-header"] } yarte = "0.15.7" +simd-json = { version = "0.13.8", optional = true } +axum-core = { version = "0.4.3", optional = true } +mime = { version = "0.3.17", optional = true } +bytes = { version = "1.5.0", optional = true } +serde_path_to_error = { version = "0.1.15", optional = true } +moka = { version = "0.12.8", features = ["future"] } +socket2 = "0.5.7" +hyper = { version = "1.4", features = ["server", "http1"] } +hyper-util = { version = "0.1", features = ["tokio", "server-auto", "http1"] } + [profile.release] -lto = true +lto = "fat" codegen-units = 1 +strip = true +opt-level = 3 diff --git a/frameworks/Rust/axum/README.md b/frameworks/Rust/axum/README.md index 55ca3e0978e..59979fe441d 100755 --- a/frameworks/Rust/axum/README.md +++ b/frameworks/Rust/axum/README.md @@ -1,42 +1,46 @@ - -# [Axum](https://github.com/tokio-rs/axum) - Ergonomic and modular web framework built with Tokio, Tower, and Hyper +# [Axum](https://github.com/tokio-rs/axum) ## Description -Axum is a web application framework that focuses on ergonomics and modularity. - -* [User Guide](https://docs.rs/axum/0.3/axum/) -* [API Documentation](https://docs.rs/axum/0.3/axum/) -* Cargo package: [axum](https://crates.io/crates/axum) +Axum is a web application framework that focuses on ergonomics and modularity, +built with Tokio, Tower, and Hyper. -## Database +- [User Guide](https://docs.rs/axum/latest/axum/) +- [API Documentation](https://docs.rs/axum/latest/axum/) +- [Cargo Package (`axum`)](https://crates.io/crates/axum) -PostgreSQL +## Variants -* Raw using [sqlx](https://github.com/launchbadge/sqlx) +- PostgreSQL using `SQLx`, `tokio_postgres`, and `deadpool`. +- MongoDB with `mongodb`. ## Test URLs -### Test 1: JSON Encoding - - http://localhost:8000/json - -### Test 2: Single Row Query - - http://localhost:8000/db - -### Test 3: Multi Row Query - - http://localhost:8000/queries?q=20 - -### Test 4: Fortunes (Template rendering) - - http://localhost:8000/fortunes - -### Test 5: Update Query - - http://localhost:8000/updates?q=20 - -### Test 6: Plaintext - - http://localhost:8000/plaintext +- Plaintext: http://localhost:8000/plaintext +- JSON Encoding: http://localhost:8000/json +- Single Row Query: http://localhost:8000/db +- Multi Row Query: http://localhost:8000/queries?q=20 +- Fortunes: http://localhost:8000/fortunes +- Update Query: http://localhost:8000/updates?q=20 +- Cached Query: http://localhost:8000/cached-queries?q=20 + +## Notable Points (both performance and build) + +- Use of `async`. +- Use of most recent versions of Rust, `axum` and dependencies. +- (Disabled by default) Compile-time swap-in of `simd-json` instead of `serde_json` for faster JSON serialization. +- Release binaries are stripped and compiled with CPU native. +- Sockets configured with TCP_NODELAY and to support an increased number of pending connections. +- Server configured to serve HTTP/1 only, with no need for websockets. +- Separation of build and deployment containers using multi-stage builds. +- Deployment into Google's minimal `distroless-cc` container. +- Use of pipelined database queries (where supported). +- Streaming database queries (where supported). +- Use of PostgreSQL prepared statements cache (where supported). +- Use of PostgreSQL arrays to execute multi-row database updates with a single `UPDATE` query. + - This is permitted by the [test requirements](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates), step (ix). +- In version 0.7.6 (as yet unreleased), a native API to set TCP_NODELAY will be included. + - https://github.com/tokio-rs/axum/pull/2653/ + - https://github.com/tokio-rs/axum/issues/2521 +- More performance improvements are to be expected in version 0.8: + - https://github.com/tokio-rs/axum/issues/1827 diff --git a/frameworks/Rust/axum/axum-mongo-raw.dockerfile b/frameworks/Rust/axum/axum-mongo-raw.dockerfile deleted file mode 100644 index ffdabfc2d8c..00000000000 --- a/frameworks/Rust/axum/axum-mongo-raw.dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM rust:1.75-slim-buster - -ENV AXUM_TECHEMPOWER_MONGODB_URL=mongodb://tfb-database:27017 -ENV AXUM_TECHEMPOWER_MAX_POOL_SIZE=28 -ENV AXUM_TECHEMPOWER_MIN_POOL_SIZE=14 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - -ENV RUSTFLAGS "-C target-cpu=native" -RUN cargo build --release -RUN cp ./target/release/axum-mongo-raw ./target/release/axum-techempower - -EXPOSE 8000 - -CMD ["./run.sh"] diff --git a/frameworks/Rust/axum/axum-mongo.dockerfile b/frameworks/Rust/axum/axum-mongo.dockerfile deleted file mode 100644 index 99a6f76f997..00000000000 --- a/frameworks/Rust/axum/axum-mongo.dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM rust:1.75-slim-buster - -ENV AXUM_TECHEMPOWER_MONGODB_URL=mongodb://tfb-database:27017 -ENV AXUM_TECHEMPOWER_MAX_POOL_SIZE=28 -ENV AXUM_TECHEMPOWER_MIN_POOL_SIZE=14 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - pkg-config libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - -ENV RUSTFLAGS "-C target-cpu=native" -RUN cargo build --release -RUN cp ./target/release/axum-mongo ./target/release/axum-techempower - -EXPOSE 8000 - -CMD ["./run.sh"] diff --git a/frameworks/Rust/axum/axum-pg-pool.dockerfile b/frameworks/Rust/axum/axum-pg-pool.dockerfile deleted file mode 100644 index c836faa2381..00000000000 --- a/frameworks/Rust/axum/axum-pg-pool.dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM rust:1.75-slim-buster - -ENV AXUM_TECHEMPOWER_DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world -ENV AXUM_TECHEMPOWER_MAX_POOL_SIZE=28 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - libpq-dev pkg-config libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - -ENV RUSTFLAGS "-C target-cpu=native" -RUN cargo build --release -RUN cp ./target/release/axum-pg-pool ./target/release/axum-techempower - -EXPOSE 8000 - -CMD ["./run.sh"] diff --git a/frameworks/Rust/axum/axum-pg.dockerfile b/frameworks/Rust/axum/axum-pg.dockerfile deleted file mode 100644 index 98d44481007..00000000000 --- a/frameworks/Rust/axum/axum-pg.dockerfile +++ /dev/null @@ -1,23 +0,0 @@ -FROM rust:1.75-slim-buster - -ENV AXUM_TECHEMPOWER_DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world - -RUN apt-get update && apt-get install -y --no-install-recommends \ - libpq-dev pkg-config libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - -ENV RUSTFLAGS "-C target-cpu=native" -RUN cargo build --release -RUN cp ./target/release/axum-pg ./target/release/axum-techempower - -EXPOSE 8000 - -CMD ["./run.sh"] diff --git a/frameworks/Rust/axum/axum-sqlx.dockerfile b/frameworks/Rust/axum/axum-sqlx.dockerfile deleted file mode 100644 index 0cecda65f32..00000000000 --- a/frameworks/Rust/axum/axum-sqlx.dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM rust:1.75-slim-buster - -ENV AXUM_TECHEMPOWER_DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world -ENV AXUM_TECHEMPOWER_MAX_POOL_SIZE=56 -ENV AXUM_TECHEMPOWER_MIN_POOL_SIZE=56 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - libpq-dev pkg-config libssl-dev \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - -ENV RUSTFLAGS "-C target-cpu=native" -RUN cargo build --release -RUN cp ./target/release/axum-sqlx ./target/release/axum-techempower - - -EXPOSE 8000 - -CMD ["./run.sh"] diff --git a/frameworks/Rust/axum/axum.dockerfile b/frameworks/Rust/axum/axum.dockerfile index 2cd772a3426..044e68bbf02 100644 --- a/frameworks/Rust/axum/axum.dockerfile +++ b/frameworks/Rust/axum/axum.dockerfile @@ -1,21 +1,24 @@ -FROM rust:1.75-slim-buster +FROM docker.io/rust:1.80-slim-bookworm AS builder RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config libssl-dev \ && rm -rf /var/lib/apt/lists/* -WORKDIR /axum -COPY ./src ./src -COPY ./templates ./templates -COPY ./Cargo.toml ./Cargo.toml -COPY ./Cargo.lock ./Cargo.lock -COPY ./run.sh ./run.sh -RUN chmod +x ./run.sh - +WORKDIR /build +COPY ./Cargo.toml ./Cargo.lock /build/ +RUN cargo fetch +COPY ./templates/ /build/templates +COPY ./src/ /build/src ENV RUSTFLAGS "-C target-cpu=native" RUN cargo build --release -RUN cp ./target/release/axum ./target/release/axum-techempower +FROM gcr.io/distroless/cc-debian12 +ENV POSTGRES_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world +ENV POSTGRES_MIN_POOL_SIZE=56 +ENV POSTGRES_MAX_POOL_SIZE=56 +ENV MONGODB_URL=mongodb://tfb-database:27017 +ENV MONGODB_MIN_POOL_SIZE=28 +ENV MONGODB_MAX_POOL_SIZE=14 +COPY --from=builder /build/target/release/axum* /app/ EXPOSE 8000 - -CMD ["./run.sh"] +CMD ["/app/axum"] diff --git a/frameworks/Rust/axum/benchmark_config.json b/frameworks/Rust/axum/benchmark_config.json index f05dd4a67dd..ade60875389 100755 --- a/frameworks/Rust/axum/benchmark_config.json +++ b/frameworks/Rust/axum/benchmark_config.json @@ -3,6 +3,8 @@ "tests": [ { "default": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum", "json_url": "/json", "plaintext_url": "/plaintext", "port": 8000, @@ -22,8 +24,11 @@ "versus": "None" }, "sqlx": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum-sqlx", "db_url": "/db", "fortune_url": "/fortunes", + "cached_query_url": "/cached-queries?queries=", "port": 8000, "approach": "Realistic", "classification": "Fullstack", @@ -41,6 +46,8 @@ "versus": "None" }, "pg": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum-pg", "db_url": "/db", "fortune_url": "/fortunes", "query_url": "/queries?queries=", @@ -62,6 +69,8 @@ "versus": "None" }, "pg-pool": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum-pg-pool", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", @@ -83,6 +92,8 @@ "versus": "None" }, "mongo": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum-mongo", "db_url": "/db", "query_url": "/queries?queries=", "fortune_url": "/fortunes", @@ -104,6 +115,8 @@ "versus": "None" }, "mongo-raw": { + "dockerfile": "axum.dockerfile", + "docker_cmd": "/app/axum-mongo-raw", "db_url": "/db", "query_url": "/queries?queries=", "update_url": "/updates?queries=", diff --git a/frameworks/Rust/axum/config.toml b/frameworks/Rust/axum/config.toml index d4bb9d7ad0e..b5695c19bf0 100644 --- a/frameworks/Rust/axum/config.toml +++ b/frameworks/Rust/axum/config.toml @@ -8,6 +8,7 @@ urls.db = "/db" urls.query = "/queries?q=" urls.update = "/updates?q=" urls.fortune = "/fortunes" +urls.cached_query = "/cached-queries?q=" approach = "Realistic" classification = "Fullstack" database = "Postgres" @@ -16,4 +17,4 @@ os = "Linux" orm = "Raw" platform = "Rust" webserver = "Hyper" -versus = "None" \ No newline at end of file +versus = "None" diff --git a/frameworks/Rust/axum/src/common/mod.rs b/frameworks/Rust/axum/src/common/mod.rs new file mode 100644 index 00000000000..d55958155f1 --- /dev/null +++ b/frameworks/Rust/axum/src/common/mod.rs @@ -0,0 +1,51 @@ +use std::{env, str::FromStr}; + +use core::fmt::Debug; +use rand::{distributions::Uniform, rngs::SmallRng, Rng}; +pub mod models; +pub mod utils; + +#[cfg(feature = "simd-json")] +pub mod simd_json; + +#[allow(dead_code)] +pub const SELECT_ALL_FORTUNES: &str = "SELECT * FROM fortune"; +#[allow(dead_code)] +pub const SELECT_WORLD_BY_ID: &str = + "SELECT id, randomnumber FROM world WHERE id = $1 LIMIT 1"; +#[allow(dead_code)] +pub const SELECT_ALL_CACHED_WORLDS: &str = + "SELECT id, randomnumber FROM world ORDER BY id"; +#[allow(dead_code)] +pub const UPDATE_WORLDS: &str = "WITH vals AS (SELECT * FROM UNNEST($1::int[], $2::int[]) AS v(id, rnum)) + UPDATE world SET randomnumber = new.rnum FROM + (SELECT w.id, v.rnum FROM world w INNER JOIN vals v ON v.id = w.id ORDER BY w.id FOR UPDATE) AS new + WHERE world.id = new.id"; + +/// Return the value of an environment variable. +#[allow(dead_code)] +pub fn get_env(key: &str) -> T +where + ::Err: Debug, +{ + env::var(key) + .unwrap_or_else(|_| panic!("{key} environment variable was not set")) + .parse::() + .unwrap_or_else(|_| panic!("could not parse {key}")) +} + +/// Generate a single integer in the range 1 to 10,000 (inclusive) +#[allow(dead_code)] +#[inline] +pub fn random_id(rng: &mut SmallRng) -> i32 { + rng.gen_range(1..10_001) +} + +/// Generate vector of integers in the range 1 to 10,000 (inclusive) +#[allow(dead_code)] +#[inline] +pub fn random_ids(rng: &mut SmallRng, count: usize) -> Vec { + rng.sample_iter(Uniform::new(1, 10_001)) + .take(count) + .collect() +} diff --git a/frameworks/Rust/axum/src/models_mongo.rs b/frameworks/Rust/axum/src/common/models.rs similarity index 85% rename from frameworks/Rust/axum/src/models_mongo.rs rename to frameworks/Rust/axum/src/common/models.rs index 31c76cc7c07..1644447c3cd 100644 --- a/frameworks/Rust/axum/src/models_mongo.rs +++ b/frameworks/Rust/axum/src/common/models.rs @@ -1,5 +1,10 @@ use serde::{Deserialize, Serialize}; +#[derive(Serialize)] +pub struct Message { + pub message: &'static str, +} + #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct Fortune { pub id: i32, diff --git a/frameworks/Rust/axum/src/common/simd_json.rs b/frameworks/Rust/axum/src/common/simd_json.rs new file mode 100644 index 00000000000..e8a2aafeee1 --- /dev/null +++ b/frameworks/Rust/axum/src/common/simd_json.rs @@ -0,0 +1,152 @@ +use axum::extract::rejection::JsonRejection::MissingJsonContentType; +use axum::extract::Request; +use axum::extract::{rejection::*, FromRequest}; +use axum::{async_trait, http}; +use axum_core::response::{IntoResponse, Response}; +use bytes::{BufMut, Bytes, BytesMut}; +use http::{ + header::{self, HeaderMap, HeaderValue}, + StatusCode, +}; +use serde::{de::DeserializeOwned, Serialize}; +use simd_json; + +#[derive(Debug, Clone, Copy, Default)] +pub struct Json(pub T); + +pub enum SimdJsonRejection { + Json(JsonRejection), + Bytes(BytesRejection), + Simd(String), +} + +impl IntoResponse for SimdJsonRejection { + fn into_response(self) -> Response { + todo!() + } +} + +impl From for SimdJsonRejection { + fn from(err: JsonRejection) -> Self { + SimdJsonRejection::Json(err) + } +} + +impl From for SimdJsonRejection { + fn from(err: BytesRejection) -> Self { + SimdJsonRejection::Bytes(err) + } +} + +impl From for SimdJsonRejection { + fn from(err: simd_json::Error) -> Self { + SimdJsonRejection::Simd(err.to_string()) + } +} + +#[async_trait] +impl FromRequest for Json +where + T: DeserializeOwned, + S: Send + Sync, +{ + type Rejection = SimdJsonRejection; + + async fn from_request(req: Request, state: &S) -> Result { + if json_content_type(req.headers()) { + let bytes = Bytes::from_request(req, state).await?; + Self::from_bytes(&bytes) + } else { + Err(SimdJsonRejection::Json(MissingJsonContentType( + axum::extract::rejection::MissingJsonContentType::default(), + ))) + } + } +} + +fn json_content_type(headers: &HeaderMap) -> bool { + let content_type = if let Some(content_type) = headers.get(header::CONTENT_TYPE) { + content_type + } else { + return false; + }; + + let content_type = if let Ok(content_type) = content_type.to_str() { + content_type + } else { + return false; + }; + + let mime = if let Ok(mime) = content_type.parse::() { + mime + } else { + return false; + }; + + let is_json_content_type = mime.type_() == "application" + && (mime.subtype() == "json" + || mime.suffix().map_or(false, |name| name == "json")); + + is_json_content_type +} + +axum_core::__impl_deref!(Json); + +impl From for Json { + fn from(inner: T) -> Self { + Self(inner) + } +} + +impl Json +where + T: DeserializeOwned, +{ + /// Construct a `Json` from a byte slice. Most users should prefer to use the `FromRequest` impl + /// but special cases may require first extracting a `Request` into `Bytes` then optionally + /// constructing a `Json`. + pub fn from_bytes(bytes: &[u8]) -> Result { + let body = &mut bytes.to_owned(); + let deserializer = simd_json::from_slice::(body); + + let value = match deserializer { + Ok(v) => v, + Err(err) => { + let rejection = { SimdJsonRejection::from(err) }; + return Err(rejection); + } + }; + + Ok(Json(value)) + } +} + +impl IntoResponse for Json +where + T: Serialize, +{ + fn into_response(self) -> Response { + // Use a small initial capacity of 128 bytes like serde_json::to_vec + // https://docs.rs/serde_json/1.0.82/src/serde_json/ser.rs.html#2189 + let mut buf = BytesMut::with_capacity(128).writer(); + match simd_json::to_writer(&mut buf, &self.0) { + Ok(()) => ( + [( + header::CONTENT_TYPE, + HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()), + )], + buf.into_inner().freeze(), + ) + .into_response(), + Err(err) => ( + StatusCode::INTERNAL_SERVER_ERROR, + [( + header::CONTENT_TYPE, + HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()), + )], + err.to_string(), + ) + .into_response(), + } + } +} diff --git a/frameworks/Rust/axum/src/utils.rs b/frameworks/Rust/axum/src/common/utils.rs similarity index 65% rename from frameworks/Rust/axum/src/utils.rs rename to frameworks/Rust/axum/src/common/utils.rs index 89ecaeae6ab..063411f3da7 100644 --- a/frameworks/Rust/axum/src/utils.rs +++ b/frameworks/Rust/axum/src/common/utils.rs @@ -1,35 +1,17 @@ -use std::{env, fmt::Debug, str::FromStr}; - use axum::{ - body::{Bytes, Full}, + body::Bytes, http::{header, HeaderValue, StatusCode}, response::{IntoResponse, Response}, }; -use rand::{rngs::SmallRng, Rng}; use serde::Deserialize; -pub fn get_environment_variable(key: &str) -> T -where - ::Err: Debug, -{ - env::var(key) - .unwrap_or_else(|_| panic!("{key} environment variable was not set")) - .parse::() - .unwrap_or_else(|_| panic!("could not parse {key}")) -} - #[derive(Debug, Deserialize)] pub struct Params { queries: Option, } #[allow(dead_code)] -pub fn random_number(rng: &mut SmallRng) -> i32 { - (rng.gen::() % 10_000 + 1) as i32 -} - -#[allow(dead_code)] -pub fn parse_params(params: Params) -> i32 { +pub fn parse_params(params: Params) -> usize { params .queries .and_then(|q| q.parse().ok()) @@ -52,7 +34,7 @@ pub struct Utf8Html(pub T); impl IntoResponse for Utf8Html where - T: Into>, + T: Into, { fn into_response(self) -> Response { let mut res = (StatusCode::OK, self.0.into()).into_response(); diff --git a/frameworks/Rust/axum/src/database_pg.rs b/frameworks/Rust/axum/src/database_pg.rs deleted file mode 100644 index 56e07553af3..00000000000 --- a/frameworks/Rust/axum/src/database_pg.rs +++ /dev/null @@ -1,199 +0,0 @@ -use std::{collections::HashMap, convert::Infallible, fmt::Write, io, sync::Arc}; - -use axum::{async_trait, extract::FromRequestParts, http::request::Parts}; -use futures::{ - stream::futures_unordered::FuturesUnordered, FutureExt, StreamExt, TryStreamExt, -}; -use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng}; -use tokio::pin; -use tokio_postgres::{connect, types::ToSql, Client, NoTls, Statement}; - -use crate::models_pg::{Fortune, World}; - -#[derive(Debug)] -pub enum PgError { - Io(io::Error), - Pg(tokio_postgres::Error), -} - -impl From for PgError { - fn from(err: io::Error) -> Self { - PgError::Io(err) - } -} - -impl From for PgError { - fn from(err: tokio_postgres::Error) -> Self { - PgError::Pg(err) - } -} - -/// Postgres interface -pub struct PgConnection { - client: Client, - fortune: Statement, - world: Statement, - updates: HashMap, -} - -impl PgConnection { - pub async fn connect(db_url: String) -> Arc { - let (cl, conn) = connect(&db_url, NoTls) - .await - .expect("can not connect to postgresql"); - - // Spawn connection - tokio::spawn(async move { - if let Err(error) = conn.await { - eprintln!("Connection error: {error}"); - } - }); - - let fortune = cl.prepare("SELECT * FROM fortune").await.unwrap(); - let mut updates = HashMap::new(); - - for num in 1..=500u16 { - let mut pl = 1; - let mut q = String::new(); - - q.push_str("UPDATE world SET randomnumber = CASE id "); - - for _ in 1..=num { - let _ = write!(q, "when ${pl} then ${} ", pl + 1); - pl += 2; - } - - q.push_str("ELSE randomnumber END WHERE id IN ("); - - for _ in 1..=num { - let _ = write!(q, "${pl},"); - pl += 1; - } - - q.pop(); - q.push(')'); - - updates.insert(num, cl.prepare(&q).await.unwrap()); - } - - let world = cl.prepare("SELECT * FROM world WHERE id=$1").await.unwrap(); - - Arc::new(PgConnection { - client: cl, - fortune, - world, - updates, - }) - } -} - -impl PgConnection { - async fn query_one_world(&self, id: i32) -> Result { - let stream = self.client.query_raw(&self.world, &[&id]).await?; - pin!(stream); - let row = stream.next().await.unwrap()?; - Ok(World { - id: row.get(0), - randomnumber: row.get(1), - }) - } - - pub async fn get_world(&self) -> Result { - let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - let world = self.query_one_world(random_id).await?; - Ok(world) - } - - pub async fn get_worlds(&self, num: usize) -> Result, PgError> { - let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - - let worlds = FuturesUnordered::new(); - - for _ in 0..num { - let w_id = (rng.gen::() % 10_000 + 1) as i32; - worlds.push(self.query_one_world(w_id)); - } - - worlds.try_collect().await - } - - pub async fn update(&self, num: u16) -> Result, PgError> { - let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - - let worlds = FuturesUnordered::new(); - - for _ in 0..num { - let id = (rng.gen::() % 10_000 + 1) as i32; - let w_id = (rng.gen::() % 10_000 + 1) as i32; - - worlds.push(self.query_one_world(w_id).map(move |res| match res { - Ok(mut world) => { - world.randomnumber = id; - Ok(world) - } - - Err(err) => Err(err), - })); - } - - let st = self.updates.get(&num).unwrap().clone(); - - let worlds: Vec = worlds.try_collect().await?; - - let mut params: Vec<&(dyn ToSql + Sync)> = Vec::with_capacity(num as usize * 3); - - for w in &worlds { - params.push(&w.id); - params.push(&w.randomnumber); - } - - for w in &worlds { - params.push(&w.id); - } - - self.client.query(&st, ¶ms[..]).await?; - - Ok(worlds) - } - - pub async fn tell_fortune(&self) -> Result, PgError> { - let mut items = vec![Fortune { - id: 0, - message: "Additional fortune added at request time.".parse().unwrap(), - }]; - - let fut = self.client.query_raw::<_, _, &[i32; 0]>(&self.fortune, &[]); - - let stream = fut.await?; - pin!(stream); - - while let Some(row) = stream.next().await { - let row = row?; - - items.push(Fortune { - id: row.get(0), - message: row.get(1), - }); - } - - items.sort_by(|it, next| it.message.cmp(&next.message)); - Ok(items) - } -} - -pub struct DatabaseConnection(pub Arc); - -#[async_trait] -impl FromRequestParts> for DatabaseConnection { - type Rejection = Infallible; - - async fn from_request_parts( - _parts: &mut Parts, - pg_connection: &Arc, - ) -> Result { - Ok(Self(pg_connection.clone())) - } -} diff --git a/frameworks/Rust/axum/src/database_sqlx.rs b/frameworks/Rust/axum/src/database_sqlx.rs deleted file mode 100644 index b156bb3a3b7..00000000000 --- a/frameworks/Rust/axum/src/database_sqlx.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::io; - -use axum::{ - async_trait, - extract::FromRequestParts, - http::{request::Parts, StatusCode}, -}; -use sqlx::{ - pool::PoolConnection, - postgres::{PgArguments, PgPoolOptions}, - Arguments, PgPool, Postgres, -}; - -use crate::{utils::internal_error, Fortune, World}; - -#[derive(Debug)] -pub enum PgError { - Io(io::Error), - Pg(sqlx::Error), -} - -impl From for PgError { - fn from(err: io::Error) -> Self { - PgError::Io(err) - } -} - -impl From for PgError { - fn from(err: sqlx::Error) -> Self { - PgError::Pg(err) - } -} - -pub async fn create_pool( - database_url: String, - max_pool_size: u32, - min_pool_size: u32, -) -> PgPool { - PgPoolOptions::new() - .max_connections(max_pool_size) - .min_connections(min_pool_size) - .connect(&database_url) - .await - .unwrap() -} - -pub struct DatabaseConnection(pub PoolConnection); - -#[async_trait] -impl FromRequestParts for DatabaseConnection { - type Rejection = (StatusCode, String); - - async fn from_request_parts( - _parts: &mut Parts, - pool: &PgPool, - ) -> Result { - let conn = pool.acquire().await.map_err(internal_error)?; - - Ok(Self(conn)) - } -} - -pub async fn fetch_world( - mut conn: PoolConnection, - number: i32, -) -> Result { - let mut args = PgArguments::default(); - args.add(number); - - let world: World = - sqlx::query_as_with("SELECT id, randomnumber FROM World WHERE id = $1", args) - .fetch_one(&mut *conn) - .await - .expect("error loading world"); - Ok(world) -} - -pub async fn fetch_fortunes( - mut conn: PoolConnection, -) -> Result, PgError> { - let fortunes: Vec = sqlx::query_as("SELECT * FROM Fortune") - .fetch_all(&mut *conn) - .await - .expect("error loading Fortunes"); - Ok(fortunes) -} diff --git a/frameworks/Rust/axum/src/main.rs b/frameworks/Rust/axum/src/main.rs index 075ee1c01e6..b29da958d20 100644 --- a/frameworks/Rust/axum/src/main.rs +++ b/frameworks/Rust/axum/src/main.rs @@ -1,21 +1,21 @@ -use axum::{ - http::{header, HeaderValue, StatusCode}, - response::IntoResponse, - routing::get, - Json, Router, -}; -use dotenv::dotenv; -use tower_http::set_header::SetResponseHeaderLayer; - -mod models_common; +mod common; mod server; -use self::models_common::Message; +use axum::{http::StatusCode, response::IntoResponse, routing::get, Router}; +use common::models::Message; +use dotenv::dotenv; + +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; -pub async fn plaintext() -> &'static str { - "Hello, World!" +/// Return a plaintext static string. +pub async fn plaintext() -> impl IntoResponse { + (StatusCode::OK, "Hello, World!") } +/// Return a JSON message. pub async fn json() -> impl IntoResponse { let message = Message { message: "Hello, World!", @@ -28,19 +28,9 @@ pub async fn json() -> impl IntoResponse { async fn main() { dotenv().ok(); - let server_header_value = HeaderValue::from_static("Axum"); - let app = Router::new() .route("/plaintext", get(plaintext)) - .route("/json", get(json)) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )); - - server::builder() - .http1_pipeline_flush(true) - .serve(app.into_make_service()) - .await - .unwrap(); + .route("/json", get(json)); + + server::serve_hyper(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/main_mongo.rs b/frameworks/Rust/axum/src/main_mongo.rs index 8219113f583..8f7ac7961c3 100644 --- a/frameworks/Rust/axum/src/main_mongo.rs +++ b/frameworks/Rust/axum/src/main_mongo.rs @@ -1,11 +1,20 @@ +mod common; +mod mongo; +//mod mongo_raw; + use std::time::Duration; use axum::{ - extract::Query, - http::{header, HeaderValue, StatusCode}, - response::IntoResponse, - routing::get, - Json, Router, + extract::Query, http::StatusCode, response::IntoResponse, routing::get, Router, +}; + +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; +use common::{ + models::{FortuneInfo, World}, + random_ids, }; use dotenv::dotenv; use mongodb::{ @@ -13,21 +22,16 @@ use mongodb::{ Client, }; use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng}; -use tower_http::set_header::SetResponseHeaderLayer; use yarte::Template; -mod database_mongo; -mod models_common; -mod models_mongo; mod server; -mod utils; - -use self::{ - database_mongo::{ - fetch_fortunes, find_world_by_id, find_worlds, update_worlds, DatabaseConnection, - }, - models_mongo::{Fortune, FortuneInfo, World}, - utils::{get_environment_variable, parse_params, Params, Utf8Html}, + +use common::{ + get_env, + utils::{parse_params, Params, Utf8Html}, +}; +use mongo::database::{ + fetch_fortunes, find_world_by_id, find_worlds, update_worlds, DatabaseConnection, }; #[derive(Template)] @@ -55,13 +59,7 @@ async fn queries( let q = parse_params(params); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let mut ids: Vec = Vec::with_capacity(q as usize); - - for _ in 0..q { - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - ids.push(random_id); - } + let ids = random_ids(&mut rng, q); let worlds = find_worlds(db, ids).await; let results = worlds.expect("worlds could not be retrieved"); @@ -76,18 +74,12 @@ async fn updates( let q = parse_params(params); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let mut ids: Vec = Vec::with_capacity(q as usize); - - for _ in 0..q { - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - ids.push(random_id); - } + let ids = random_ids(&mut rng, q); let worlds = find_worlds(db.clone(), ids) .await .expect("worlds could not be retrieved"); - let mut updated_worlds: Vec = Vec::with_capacity(q as usize); + let mut updated_worlds: Vec = Vec::with_capacity(q); for mut world in worlds { let random_number = (rng.gen::() % 10_000 + 1) as i32; @@ -144,9 +136,9 @@ fn main() { } async fn serve() { - let database_url: String = get_environment_variable("AXUM_TECHEMPOWER_MONGODB_URL"); - let max_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MAX_POOL_SIZE"); - let min_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MIN_POOL_SIZE"); + let database_url: String = get_env("MONGODB_URL"); + let max_pool_size: u32 = get_env("MONGODB_MAX_POOL_SIZE"); + let min_pool_size: u32 = get_env("MONGODB_MIN_POOL_SIZE"); let mut client_options = ClientOptions::parse(database_url).await.unwrap(); @@ -168,21 +160,13 @@ async fn serve() { let client = Client::with_options(client_options).unwrap(); let database = client.database("hello_world"); - let server_header_value = HeaderValue::from_static("Axum"); let app = Router::new() .route("/fortunes", get(fortunes)) .route("/db", get(db)) .route("/queries", get(queries)) .route("/updates", get(updates)) - .with_state(database) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )); - - server::builder() - .serve(app.into_make_service()) - .await - .unwrap(); + .with_state(database); + + server::serve(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/main_mongo_raw.rs b/frameworks/Rust/axum/src/main_mongo_raw.rs index 72db28af280..fdf09c179a3 100644 --- a/frameworks/Rust/axum/src/main_mongo_raw.rs +++ b/frameworks/Rust/axum/src/main_mongo_raw.rs @@ -1,38 +1,38 @@ +mod common; +mod mongo_raw; +mod server; + +use common::{models::World, random_id, random_ids}; +use mongo_raw::database::{ + find_world_by_id, find_worlds, update_worlds, DatabaseConnection, +}; + +use common::{ + get_env, + utils::{parse_params, Params}, +}; use std::time::Duration; use axum::{ - extract::Query, - http::{header, HeaderValue, StatusCode}, - response::IntoResponse, - routing::get, - Json, Router, + extract::Query, http::StatusCode, response::IntoResponse, routing::get, Router, }; + +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; + use dotenv::dotenv; use mongodb::{ options::{ClientOptions, Compressor}, Client, }; use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng}; -use tower_http::set_header::SetResponseHeaderLayer; - -mod database_mongo_raw; -mod models_common; -mod models_mongo; -mod server; -mod utils; - -use self::{ - database_mongo_raw::{ - find_world_by_id, find_worlds, update_worlds, DatabaseConnection, - }, - models_mongo::World, - utils::{get_environment_variable, parse_params, Params}, -}; async fn db(DatabaseConnection(db): DatabaseConnection) -> impl IntoResponse { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let random_id = (rng.gen::() % 10_000 + 1) as i32; + let random_id = random_id(&mut rng); let world = find_world_by_id(db, random_id) .await @@ -48,13 +48,7 @@ async fn queries( let q = parse_params(params); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let mut ids: Vec = Vec::with_capacity(q as usize); - - for _ in 0..q { - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - ids.push(random_id); - } + let ids = random_ids(&mut rng, q); let worlds = find_worlds(db, ids).await; let results = worlds.expect("worlds could not be retrieved"); @@ -69,18 +63,12 @@ async fn updates( let q = parse_params(params); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let mut ids: Vec = Vec::with_capacity(q as usize); - - for _ in 0..q { - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - ids.push(random_id); - } + let ids = random_ids(&mut rng, q); let worlds = find_worlds(db.clone(), ids) .await .expect("worlds could not be retrieved"); - let mut updated_worlds: Vec = Vec::with_capacity(q as usize); + let mut updated_worlds: Vec = Vec::with_capacity(q); for mut world in worlds { let random_number = (rng.gen::() % 10_000 + 1) as i32; @@ -117,9 +105,9 @@ fn main() { } async fn serve() { - let database_url: String = get_environment_variable("AXUM_TECHEMPOWER_MONGODB_URL"); - let max_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MAX_POOL_SIZE"); - let min_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MIN_POOL_SIZE"); + let database_url: String = get_env("MONGODB_URL"); + let max_pool_size: u32 = get_env("MONGODB_MAX_POOL_SIZE"); + let min_pool_size: u32 = get_env("MONGODB_MIN_POOL_SIZE"); let mut client_options = ClientOptions::parse(database_url).await.unwrap(); @@ -141,20 +129,12 @@ async fn serve() { let client = Client::with_options(client_options).unwrap(); let database = client.database("hello_world"); - let server_header_value = HeaderValue::from_static("Axum"); let app = Router::new() .route("/db", get(db)) .route("/queries", get(queries)) .route("/updates", get(updates)) - .with_state(database) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )); - - server::builder() - .serve(app.into_make_service()) - .await - .unwrap(); + .with_state(database); + + server::serve(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/main_pg.rs b/frameworks/Rust/axum/src/main_pg.rs index 3b4748dfc39..20acb2a1769 100644 --- a/frameworks/Rust/axum/src/main_pg.rs +++ b/frameworks/Rust/axum/src/main_pg.rs @@ -1,25 +1,26 @@ +mod common; +mod pg; + use axum::{ - extract::Query, - http::{header, HeaderValue, StatusCode}, - response::IntoResponse, - routing::get, - Json, Router, + extract::Query, http::StatusCode, response::IntoResponse, routing::get, Router, }; use dotenv::dotenv; -use tower_http::set_header::SetResponseHeaderLayer; +use rand::{rngs::SmallRng, thread_rng, SeedableRng}; use yarte::Template; -mod database_pg; -mod models_common; -mod models_pg; +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; + mod server; -mod utils; -use self::{ - database_pg::{DatabaseConnection, PgConnection}, - models_pg::Fortune, - utils::{get_environment_variable, parse_params, Params, Utf8Html}, +use common::{ + get_env, random_id, + utils::{parse_params, Params, Utf8Html}, }; +use pg::database::{DatabaseConnection, PgConnection}; +use pg::models::Fortune; #[derive(Template)] #[template(path = "fortunes.html.hbs")] @@ -28,7 +29,12 @@ pub struct FortunesTemplate<'a> { } async fn db(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResponse { - let world = conn.get_world().await.expect("error loading world"); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + + let world = conn + .fetch_world_by_id(random_id(&mut rng)) + .await + .expect("error loading world"); (StatusCode::OK, Json(world)) } @@ -40,7 +46,7 @@ async fn queries( let q = parse_params(params); let results = conn - .get_worlds(q as usize) + .fetch_random_worlds(q) .await .expect("error loading worlds"); @@ -48,8 +54,10 @@ async fn queries( } async fn fortunes(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResponse { - let fortunes: Vec = - conn.tell_fortune().await.expect("error loading fortunes"); + let fortunes: Vec = conn + .fetch_all_fortunes() + .await + .expect("error loading fortunes"); Utf8Html( FortunesTemplate { @@ -65,52 +73,26 @@ async fn updates( Query(params): Query, ) -> impl IntoResponse { let q = parse_params(params); + let worlds = conn.update_worlds(q).await.expect("error updating worlds"); - let results = conn.update(q as u16).await.expect("error updating worlds"); - - (StatusCode::OK, Json(results)) + (StatusCode::OK, Json(worlds)) } -fn main() { +#[tokio::main] +async fn main() { dotenv().ok(); - let rt = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap(); - - for _ in 1..num_cpus::get() { - std::thread::spawn(move || { - let rt = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .unwrap(); - rt.block_on(serve()); - }); - } - rt.block_on(serve()); -} - -async fn serve() { - let database_url: String = get_environment_variable("AXUM_TECHEMPOWER_DATABASE_URL"); + let database_url: String = get_env("POSTGRES_URL"); - // setup connection pool + // Create shared database connection let pg_connection = PgConnection::connect(database_url).await; - let server_header_value = HeaderValue::from_static("Axum"); - let router = Router::new() + let app = Router::new() .route("/fortunes", get(fortunes)) .route("/db", get(db)) .route("/queries", get(queries)) .route("/updates", get(updates)) - .with_state(pg_connection) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )); - - server::builder() - .serve(router.into_make_service()) - .await - .unwrap(); + .with_state(pg_connection); + + server::serve_hyper(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/main_pg_pool.rs b/frameworks/Rust/axum/src/main_pg_pool.rs index 4c767b4a06c..d4b7754cba8 100644 --- a/frameworks/Rust/axum/src/main_pg_pool.rs +++ b/frameworks/Rust/axum/src/main_pg_pool.rs @@ -1,31 +1,31 @@ +mod common; +mod pg_pool; + use axum::{ - extract::Query, - http::{header, HeaderValue, StatusCode}, - response::IntoResponse, - routing::get, - Json, Router, + extract::Query, http::StatusCode, response::IntoResponse, routing::get, Router, }; + +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; + +use common::{random_ids, SELECT_ALL_FORTUNES, SELECT_WORLD_BY_ID, UPDATE_WORLDS}; use dotenv::dotenv; use futures_util::{stream::FuturesUnordered, TryStreamExt}; -use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng}; -use tower_http::set_header::SetResponseHeaderLayer; +use rand::{rngs::SmallRng, thread_rng, SeedableRng}; use yarte::Template; -mod database_pg_pool; -mod models_common; -mod models_pg_pool; mod server; -mod utils; - -use self::{ - database_pg_pool::{ - create_pool, fetch_all_fortunes, fetch_world_by_id, - prepare_fetch_all_fortunes_statement, prepare_fetch_world_by_id_statement, - prepare_update_world_by_id_statement, update_world, DatabaseClient, PgError, - }, - models_pg_pool::{Fortune, World}, - utils::{get_environment_variable, parse_params, random_number, Params, Utf8Html}, + +use common::{ + get_env, random_id, + utils::{parse_params, Params, Utf8Html}, }; +use pg_pool::database::{ + create_pool, fetch_all_fortunes, fetch_world_by_id, DatabaseClient, PgError, +}; +use pg_pool::models::{Fortune, World}; #[derive(Template)] #[template(path = "fortunes.html.hbs")] @@ -35,11 +35,10 @@ pub struct FortunesTemplate<'a> { async fn db(DatabaseClient(client): DatabaseClient) -> impl IntoResponse { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + let random_id = random_id(&mut rng); - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - let select = prepare_fetch_world_by_id_statement(&client).await; - let world = fetch_world_by_id(&client, random_id, &select) + let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap(); + let world = fetch_world_by_id(&client, random_id, select) .await .expect("could not fetch world"); @@ -53,15 +52,11 @@ async fn queries( let q = parse_params(params); let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - - let select = prepare_fetch_world_by_id_statement(&client).await; - + let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap(); let future_worlds = FuturesUnordered::new(); - for _ in 0..q { - let w_id = (rng.gen::() % 10_000 + 1) as i32; - - future_worlds.push(fetch_world_by_id(&client, w_id, &select)); + for id in random_ids(&mut rng, q) { + future_worlds.push(fetch_world_by_id(&client, id, select)); } let worlds: Result, PgError> = future_worlds.try_collect().await; @@ -71,9 +66,9 @@ async fn queries( } async fn fortunes(DatabaseClient(client): DatabaseClient) -> impl IntoResponse { - let select = prepare_fetch_all_fortunes_statement(&client).await; + let select = &client.prepare_cached(SELECT_ALL_FORTUNES).await.unwrap(); - let mut fortunes = fetch_all_fortunes(client, &select) + let mut fortunes = fetch_all_fortunes(client, select) .await .expect("could not fetch fortunes"); @@ -100,66 +95,49 @@ async fn updates( let q = parse_params(params); let mut rng = SmallRng::from_entropy(); + let select = &client.prepare_cached(SELECT_WORLD_BY_ID).await.unwrap(); + let update = &client.prepare_cached(UPDATE_WORLDS).await.unwrap(); - let select = prepare_fetch_world_by_id_statement(&client).await; - + // Select the random worlds. let future_worlds = FuturesUnordered::new(); - - for _ in 0..q { - let query_id = random_number(&mut rng); - - future_worlds.push(fetch_world_by_id(&client, query_id, &select)); + for id in random_ids(&mut rng, q) { + future_worlds.push(fetch_world_by_id(&client, id, select)); } - - let worlds: Result, PgError> = future_worlds.try_collect().await; - let results = worlds.expect("worlds could not be retrieved"); - - let update = prepare_update_world_by_id_statement(&client).await; - - let future_world_updates = FuturesUnordered::new(); - - for w in &results { - let random_id = random_number(&mut rng); - let w_id = w.id; - - future_world_updates.push(update_world(&client, &update, random_id, w_id)); - } - - let world_updates: Result, PgError> = - future_world_updates.try_collect().await; - world_updates.expect("updates could not be executed"); - - (StatusCode::OK, Json(results)) + let worlds: Vec = future_worlds.try_collect().await.unwrap(); + + let mut ids = Vec::with_capacity(q); + let mut nids = Vec::with_capacity(q); + let worlds: Vec = worlds + .into_iter() + .map(|mut w| { + w.randomnumber = random_id(&mut rng); + ids.push(w.id); + nids.push(w.randomnumber); + w + }) + .collect(); + + // Update the random worlds in the database. + client.execute(update, &[&ids, &nids]).await.unwrap(); + + (StatusCode::OK, Json(worlds)) } #[tokio::main] async fn main() { dotenv().ok(); - serve().await; -} - -async fn serve() { - let database_url: String = get_environment_variable("AXUM_TECHEMPOWER_DATABASE_URL"); - let max_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MAX_POOL_SIZE"); + let database_url: String = get_env("POSTGRES_URL"); + let max_pool_size: u32 = get_env("POSTGRES_MAX_POOL_SIZE"); - // setup Client pool let pool = create_pool(database_url, max_pool_size).await; - let server_header_value = HeaderValue::from_static("Axum"); - let router = Router::new() + let app = Router::new() .route("/fortunes", get(fortunes)) .route("/db", get(db)) .route("/queries", get(queries)) .route("/updates", get(updates)) - .with_state(pool) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )); - - server::builder() - .serve(router.into_make_service()) - .await - .unwrap(); + .with_state(pool); + + server::serve_hyper(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/main_sqlx.rs b/frameworks/Rust/axum/src/main_sqlx.rs index c773233fcfa..d10b1ea99ef 100644 --- a/frameworks/Rust/axum/src/main_sqlx.rs +++ b/frameworks/Rust/axum/src/main_sqlx.rs @@ -1,27 +1,35 @@ +mod common; +mod sqlx; + +use std::sync::Arc; + +use ::sqlx::PgPool; use axum::{ - http::{header, HeaderValue, StatusCode}, + extract::{Query, State}, + http::StatusCode, response::IntoResponse, routing::get, - Json, Router, + Router, }; use dotenv::dotenv; -use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng}; -use sqlx::PgPool; -use tower_http::set_header::SetResponseHeaderLayer; +use moka::future::Cache; +use rand::{rngs::SmallRng, thread_rng, SeedableRng}; +use sqlx::models::World; use yarte::Template; -mod database_sqlx; -mod models_common; -mod models_sqlx; +#[cfg(not(feature = "simd-json"))] +use axum::Json; +#[cfg(feature = "simd-json")] +use common::simd_json::Json; + mod server; -mod utils; -use self::{ - database_sqlx::{create_pool, fetch_fortunes, fetch_world, DatabaseConnection}, - models_sqlx::{Fortune, World}, - utils::get_environment_variable, - utils::Utf8Html, +use common::{ + get_env, random_id, random_ids, + utils::{parse_params, Params, Utf8Html}, }; +use sqlx::database::create_pool; +use sqlx::models::Fortune; #[derive(Template)] #[template(path = "fortunes.html.hbs")] @@ -29,22 +37,44 @@ pub struct FortunesTemplate<'a> { pub fortunes: &'a Vec, } -async fn db(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResponse { +async fn db(State(AppState { db, .. }): State) -> impl IntoResponse { let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); - let random_id = (rng.gen::() % 10_000 + 1) as i32; - - let world = fetch_world(conn, random_id) + let world: World = ::sqlx::query_as(common::SELECT_WORLD_BY_ID) + .bind(random_id(&mut rng)) + .fetch_one(&mut *db.acquire().await.unwrap()) .await - .expect("could not fetch world"); + .expect("error loading world"); (StatusCode::OK, Json(world)) } -async fn fortunes(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResponse { - let mut fortunes = fetch_fortunes(conn) +async fn queries( + State(AppState { db, .. }): State, + Query(params): Query, +) -> impl IntoResponse { + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + let count = parse_params(params); + let ids = random_ids(&mut rng, count); + let mut worlds: Vec = Vec::with_capacity(count); + + for id in ids { + let world: World = ::sqlx::query_as(common::SELECT_WORLD_BY_ID) + .bind(id) + .fetch_one(&mut *db.acquire().await.unwrap()) + .await + .expect("error loading world"); + worlds.push(world); + } + + (StatusCode::OK, Json(worlds)) +} + +async fn fortunes(State(AppState { db, .. }): State) -> impl IntoResponse { + let mut fortunes: Vec = ::sqlx::query_as(common::SELECT_ALL_FORTUNES) + .fetch_all(&mut *db.acquire().await.unwrap()) .await - .expect("could not fetch fortunes"); + .expect("error loading Fortunes"); fortunes.push(Fortune { id: 0, @@ -62,34 +92,61 @@ async fn fortunes(DatabaseConnection(conn): DatabaseConnection) -> impl IntoResp ) } -#[tokio::main] -async fn main() { - dotenv().ok(); - - let database_url: String = get_environment_variable("AXUM_TECHEMPOWER_DATABASE_URL"); - let max_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MAX_POOL_SIZE"); - let min_pool_size: u32 = get_environment_variable("AXUM_TECHEMPOWER_MIN_POOL_SIZE"); +async fn cache( + State(AppState { cache, .. }): State, + Query(params): Query, +) -> impl IntoResponse { + let count = parse_params(params); + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + let mut worlds: Vec>> = Vec::with_capacity(count); - // setup connection pool - let pool = create_pool(database_url, max_pool_size, min_pool_size).await; + for id in random_ids(&mut rng, count) { + worlds.push(cache.get(&id).await); + } - let app = router(pool).await; + (StatusCode::OK, Json(worlds)) +} - server::builder() - .serve(app.into_make_service()) +/// Pre-load the cache with all worlds. +async fn preload_cache(AppState { db, cache }: &AppState) { + let worlds: Vec = ::sqlx::query_as(common::SELECT_ALL_CACHED_WORLDS) + .fetch_all(&mut *db.acquire().await.unwrap()) .await - .unwrap(); + .expect("error loading worlds"); + + for world in worlds { + cache.insert(world.id, Arc::new(world)).await; + } } -async fn router(pool: PgPool) -> Router { - let server_header_value = HeaderValue::from_static("Axum"); +#[derive(Clone)] +struct AppState { + db: PgPool, + cache: Cache>, +} - Router::new() +#[tokio::main] +async fn main() { + dotenv().ok(); + + let database_url: String = get_env("POSTGRES_URL"); + let max_pool_size: u32 = get_env("POSTGRES_MAX_POOL_SIZE"); + let min_pool_size: u32 = get_env("POSTGRES_MIN_POOL_SIZE"); + + let state = AppState { + db: create_pool(database_url, max_pool_size, min_pool_size).await, + cache: Cache::new(10000), + }; + + // Prime the cache with CachedWorld objects + preload_cache(&state).await; + + let app = Router::new() .route("/fortunes", get(fortunes)) .route("/db", get(db)) - .with_state(pool) - .layer(SetResponseHeaderLayer::if_not_present( - header::SERVER, - server_header_value, - )) + .route("/queries", get(queries)) + .route("/cached-queries", get(cache)) + .with_state(state); + + server::serve_hyper(app, Some(8000)).await } diff --git a/frameworks/Rust/axum/src/models_common.rs b/frameworks/Rust/axum/src/models_common.rs deleted file mode 100644 index 9aed68955a4..00000000000 --- a/frameworks/Rust/axum/src/models_common.rs +++ /dev/null @@ -1,6 +0,0 @@ -use serde::Serialize; - -#[derive(Serialize)] -pub struct Message { - pub message: &'static str, -} diff --git a/frameworks/Rust/axum/src/database_mongo.rs b/frameworks/Rust/axum/src/mongo/database.rs similarity index 97% rename from frameworks/Rust/axum/src/database_mongo.rs rename to frameworks/Rust/axum/src/mongo/database.rs index dcb9b1bebb9..28c55d25c01 100644 --- a/frameworks/Rust/axum/src/database_mongo.rs +++ b/frameworks/Rust/axum/src/mongo/database.rs @@ -4,7 +4,7 @@ use axum::{async_trait, extract::FromRequestParts, http::request::Parts}; use futures_util::{stream::FuturesUnordered, StreamExt, TryStreamExt}; use mongodb::{bson::doc, Database}; -use crate::{Fortune, World}; +use crate::common::models::{Fortune, World}; pub struct DatabaseConnection(pub Database); @@ -21,6 +21,7 @@ impl FromRequestParts for DatabaseConnection { } #[derive(Debug)] +#[allow(dead_code)] pub enum MongoError { Io(io::Error), Mongo(mongodb::error::Error), diff --git a/frameworks/Rust/axum/src/mongo/mod.rs b/frameworks/Rust/axum/src/mongo/mod.rs new file mode 100644 index 00000000000..8fd0a6be869 --- /dev/null +++ b/frameworks/Rust/axum/src/mongo/mod.rs @@ -0,0 +1 @@ +pub mod database; diff --git a/frameworks/Rust/axum/src/database_mongo_raw.rs b/frameworks/Rust/axum/src/mongo_raw/database.rs similarity index 97% rename from frameworks/Rust/axum/src/database_mongo_raw.rs rename to frameworks/Rust/axum/src/mongo_raw/database.rs index 2fa02c07ec4..638c590c9fa 100644 --- a/frameworks/Rust/axum/src/database_mongo_raw.rs +++ b/frameworks/Rust/axum/src/mongo_raw/database.rs @@ -7,7 +7,7 @@ use mongodb::{ Database, }; -use crate::World; +use crate::common::models::World; pub struct DatabaseConnection(pub Database); @@ -24,6 +24,7 @@ impl FromRequestParts for DatabaseConnection { } #[derive(Debug)] +#[allow(dead_code)] pub enum MongoError { Io(io::Error), Mongo(mongodb::error::Error), diff --git a/frameworks/Rust/axum/src/mongo_raw/mod.rs b/frameworks/Rust/axum/src/mongo_raw/mod.rs new file mode 100644 index 00000000000..8fd0a6be869 --- /dev/null +++ b/frameworks/Rust/axum/src/mongo_raw/mod.rs @@ -0,0 +1 @@ +pub mod database; diff --git a/frameworks/Rust/axum/src/pg/database.rs b/frameworks/Rust/axum/src/pg/database.rs new file mode 100644 index 00000000000..bc78b2ba5c8 --- /dev/null +++ b/frameworks/Rust/axum/src/pg/database.rs @@ -0,0 +1,155 @@ +use std::{convert::Infallible, io, sync::Arc}; + +use axum::{async_trait, extract::FromRequestParts, http::request::Parts}; +use futures::{stream::futures_unordered::FuturesUnordered, StreamExt, TryStreamExt}; +use rand::{rngs::SmallRng, thread_rng, SeedableRng}; +use tokio::pin; +use tokio_postgres::{connect, Client, NoTls, Statement}; + +use crate::common::{self, random_id, random_ids}; + +use super::models::{Fortune, World}; + +#[derive(Debug)] +#[allow(dead_code)] +pub enum PgError { + Io(io::Error), + Pg(tokio_postgres::Error), +} + +impl From for PgError { + fn from(err: io::Error) -> Self { + PgError::Io(err) + } +} + +impl From for PgError { + fn from(err: tokio_postgres::Error) -> Self { + PgError::Pg(err) + } +} + +/// Postgres interface +pub struct PgConnection { + client: Client, + fortune: Statement, + world: Statement, + updates: Statement, +} + +impl PgConnection { + pub async fn connect(db_url: String) -> Arc { + let (cl, conn) = connect(&db_url, NoTls) + .await + .expect("cannot connect to postgresql."); + + // Spawn connection + tokio::spawn(async move { + if let Err(error) = conn.await { + eprintln!("database connection error: {error}"); + } + }); + + // Prepare statements for the connection. + let fortune = cl.prepare(common::SELECT_ALL_FORTUNES).await.unwrap(); + let world = cl.prepare(common::SELECT_WORLD_BY_ID).await.unwrap(); + let updates = cl.prepare(common::UPDATE_WORLDS).await.unwrap(); + + Arc::new(PgConnection { + client: cl, + fortune, + world, + updates, + }) + } +} + +impl PgConnection { + pub async fn fetch_world_by_id(&self, id: i32) -> Result { + self.client + .query_one(&self.world, &[&id]) + .await + .map(|row| { + Ok(World { + id: row.get(0), + randomnumber: row.get(1), + }) + })? + } + + pub async fn fetch_random_worlds(&self, num: usize) -> Result, PgError> { + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + + let futures = FuturesUnordered::new(); + + for id in random_ids(&mut rng, num) { + futures.push(self.fetch_world_by_id(id)); + } + + futures.try_collect().await + } + + pub async fn update_worlds(&self, num: usize) -> Result, PgError> { + let worlds = self.fetch_random_worlds(num).await?; + + // Update the worlds with new random numbers + let mut rng = SmallRng::from_rng(&mut thread_rng()).unwrap(); + let mut ids = Vec::with_capacity(num); + let mut nids = Vec::with_capacity(num); + let worlds: Vec = worlds + .into_iter() + .map(|mut w| { + w.randomnumber = random_id(&mut rng); + ids.push(w.id); + nids.push(w.randomnumber); + w + }) + .collect(); + + // Update the random worlds in the database. + self.client + .execute(&self.updates, &[&ids, &nids]) + .await + .unwrap(); + + Ok(worlds) + } + + pub async fn fetch_all_fortunes(&self) -> Result, PgError> { + let mut fortunes = vec![Fortune { + id: 0, + message: "Additional fortune added at request time.".parse().unwrap(), + }]; + + let rows = self + .client + .query_raw::<_, _, &[i32; 0]>(&self.fortune, &[]) + .await?; + + pin!(rows); + + while let Some(row) = rows.next().await.transpose()? { + fortunes.push(Fortune { + id: row.get(0), + message: row.get(1), + }); + } + + fortunes.sort_by(|it, next| it.message.cmp(&next.message)); + Ok(fortunes) + } +} + +pub struct DatabaseConnection(pub Arc); + +#[async_trait] +impl FromRequestParts> for DatabaseConnection { + type Rejection = Infallible; + + async fn from_request_parts( + _parts: &mut Parts, + pg_connection: &Arc, + ) -> Result { + Ok(Self(pg_connection.clone())) + } +} diff --git a/frameworks/Rust/axum/src/pg/mod.rs b/frameworks/Rust/axum/src/pg/mod.rs new file mode 100644 index 00000000000..c51e02d23d3 --- /dev/null +++ b/frameworks/Rust/axum/src/pg/mod.rs @@ -0,0 +1,2 @@ +pub mod database; +pub mod models; diff --git a/frameworks/Rust/axum/src/models_pg.rs b/frameworks/Rust/axum/src/pg/models.rs similarity index 100% rename from frameworks/Rust/axum/src/models_pg.rs rename to frameworks/Rust/axum/src/pg/models.rs diff --git a/frameworks/Rust/axum/src/database_pg_pool.rs b/frameworks/Rust/axum/src/pg_pool/database.rs similarity index 60% rename from frameworks/Rust/axum/src/database_pg_pool.rs rename to frameworks/Rust/axum/src/pg_pool/database.rs index f86c002845a..e1a43f34f23 100644 --- a/frameworks/Rust/axum/src/database_pg_pool.rs +++ b/frameworks/Rust/axum/src/pg_pool/database.rs @@ -1,17 +1,22 @@ use std::io; +use crate::{ + common::utils::internal_error, + pg_pool::models::{Fortune, World}, +}; use axum::{ async_trait, extract::FromRequestParts, http::{request::Parts, StatusCode}, }; use deadpool_postgres::{Client, Manager, ManagerConfig, RecyclingMethod}; +use futures_util::StreamExt; +use tokio::pin; use tokio_pg_mapper::FromTokioPostgresRow; use tokio_postgres::{NoTls, Row, Statement}; -use crate::{utils::internal_error, Fortune, World}; - #[derive(Debug)] +#[allow(dead_code)] pub enum PgError { Io(io::Error), Pg(tokio_postgres::Error), @@ -66,57 +71,26 @@ impl FromRequestParts for DatabaseClient { pub async fn fetch_world_by_id( client: &Client, - number: i32, + id: i32, select: &Statement, ) -> Result { - let row: Row = client.query_one(select, &[&number]).await.unwrap(); + let row: Row = client.query_one(select, &[&id]).await.unwrap(); Ok(World::from_row(row).unwrap()) } -pub async fn update_world( - client: &Client, - update: &Statement, - random_id: i32, - w_id: i32, -) -> Result { - let rows_modified: u64 = client.execute(update, &[&random_id, &w_id]).await.unwrap(); - - Ok(rows_modified) -} - pub async fn fetch_all_fortunes( client: Client, select: &Statement, ) -> Result, PgError> { - let rows: Vec = client.query(select, &[]).await.unwrap(); - - let mut fortunes: Vec = Vec::with_capacity(rows.capacity()); + let mut fortunes: Vec = Vec::new(); + let rows = client.query_raw::<_, _, &[i32; 0]>(select, &[]).await?; + pin!(rows); - for row in rows { - fortunes.push(Fortune::from_row(row).unwrap()); + while let Some(row) = rows.next().await.transpose()? { + fortunes + .push(Fortune::from_row(row).expect("could not convert row to fortune.")); } Ok(fortunes) } - -pub async fn prepare_fetch_all_fortunes_statement(client: &Client) -> Statement { - client - .prepare_cached("SELECT * FROM Fortune") - .await - .unwrap() -} - -pub async fn prepare_fetch_world_by_id_statement(client: &Client) -> Statement { - client - .prepare_cached("SELECT id, randomnumber FROM World WHERE id = $1") - .await - .unwrap() -} - -pub async fn prepare_update_world_by_id_statement(client: &Client) -> Statement { - client - .prepare_cached("UPDATE World SET randomnumber = $1 WHERE id = $2") - .await - .unwrap() -} diff --git a/frameworks/Rust/axum/src/pg_pool/mod.rs b/frameworks/Rust/axum/src/pg_pool/mod.rs new file mode 100644 index 00000000000..c51e02d23d3 --- /dev/null +++ b/frameworks/Rust/axum/src/pg_pool/mod.rs @@ -0,0 +1,2 @@ +pub mod database; +pub mod models; diff --git a/frameworks/Rust/axum/src/models_pg_pool.rs b/frameworks/Rust/axum/src/pg_pool/models.rs similarity index 100% rename from frameworks/Rust/axum/src/models_pg_pool.rs rename to frameworks/Rust/axum/src/pg_pool/models.rs diff --git a/frameworks/Rust/axum/src/server.rs b/frameworks/Rust/axum/src/server.rs index 29e165f6f5c..5e03a6aca88 100644 --- a/frameworks/Rust/axum/src/server.rs +++ b/frameworks/Rust/axum/src/server.rs @@ -1,37 +1,106 @@ use std::{ io, - net::{Ipv4Addr, SocketAddr}, + net::{Ipv4Addr, SocketAddr, TcpListener}, }; -use hyper::server::conn::AddrIncoming; -use tokio::net::{TcpListener, TcpSocket}; - -pub fn builder() -> hyper::server::Builder { - let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 8000)); - let listener = reuse_listener(addr).expect("couldn't bind to addr"); - let incoming = AddrIncoming::from_listener(listener).unwrap(); +use axum::{ + http::{header, HeaderValue}, + Router, +}; - println!("Started axum server at 8000"); +use hyper::body::Incoming; +use hyper::Request; +use hyper_util::rt::{TokioExecutor, TokioIo}; +use tower::Service; +use tower_http::set_header::SetResponseHeaderLayer; - axum::Server::builder(incoming) - .http1_only(true) - .tcp_nodelay(true) -} +use socket2::{Domain, Socket, Type}; -fn reuse_listener(addr: SocketAddr) -> io::Result { +/// Reuse an existing listener, ensuring that the socket `backlog`` +/// is set to enable a higher number of pending connections. +fn set_socket_options(addr: SocketAddr) -> io::Result { let socket = match addr { - SocketAddr::V4(_) => TcpSocket::new_v4()?, - SocketAddr::V6(_) => TcpSocket::new_v6()?, + SocketAddr::V4(_) => Socket::new(Domain::IPV4, Type::STREAM, None)?, + SocketAddr::V6(_) => Socket::new(Domain::IPV6, Type::STREAM, None)?, }; - #[cfg(unix)] - { - if let Err(e) = socket.set_reuseport(true) { - eprintln!("error setting SO_REUSEPORT: {e}"); - } - } + socket.set_reuse_port(true)?; + socket.set_reuse_address(true)?; + socket.set_nonblocking(true)?; + socket.set_nodelay(true)?; + socket.bind(&addr.into())?; + socket.listen(4096)?; + + let listener: TcpListener = socket.into(); + tokio::net::TcpListener::from_std(listener) +} + +/// Build an Axum server with consistent configuration, using the high-level API exposed +/// by Axum 0.7. This is intended for convenience and intentionally does not provide much +/// customisability. +#[allow(dead_code)] +pub async fn serve(app: Router<()>, port: Option) { + let port = port.unwrap_or(8000); + let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, port)); + let listener = set_socket_options(addr).expect("couldn't bind to address"); + println!("started axum server on port {port}."); + + let server_header_value = HeaderValue::from_static("Axum"); + let app = app.layer(SetResponseHeaderLayer::overriding( + header::SERVER, + server_header_value, + )); - socket.set_reuseaddr(true)?; - socket.bind(addr)?; - socket.listen(1024) + axum::serve(listener, app.into_make_service()) + .await + .unwrap(); +} + +/// Build an Axum server using the lower-level Hyper APIs for more +/// configurability. This has a few optimisations, including: +/// * Serving HTTP/1 only. +/// * Disabling connection upgrades (websockets are not needed). +/// * Setting TCP_NODELAY on the input stream. +/// * Aggregating flushes to better support pipelined responses. +/// +/// See for more details: +/// * https://github.com/tokio-rs/axum/blob/1ac617a1b540e8523347f5ee889d65cad9a45ec4/examples/serve-with-hyper/src/main.rs +#[allow(dead_code)] +pub async fn serve_hyper(app: Router<()>, port: Option) { + let port = port.unwrap_or(8000); + let addr = SocketAddr::from((Ipv4Addr::UNSPECIFIED, port)); + let listener = set_socket_options(addr).expect("couldn't bind to address"); + println!("started axum server on port {port}."); + + let server_header_value = HeaderValue::from_static("Axum"); + let app = app.layer(SetResponseHeaderLayer::overriding( + header::SERVER, + server_header_value, + )); + + // Continuously accept new connections. + loop { + let (socket, _remote_addr) = listener.accept().await.unwrap(); + socket + .set_nodelay(true) + .expect("could not set TCP_NODELAY!"); + + let tower_service = app.clone(); + tokio::spawn(async move { + let socket = TokioIo::new(socket); + + let hyper_service = + hyper::service::service_fn(move |request: Request| { + tower_service.clone().call(request) + }); + + if (hyper_util::server::conn::auto::Builder::new(TokioExecutor::new()) + .http1() + .pipeline_flush(true) + .serve_connection(socket, hyper_service) + .await) + .is_err() + {} + }); + } } diff --git a/frameworks/Rust/axum/src/sqlx/database.rs b/frameworks/Rust/axum/src/sqlx/database.rs new file mode 100644 index 00000000000..1d824144696 --- /dev/null +++ b/frameworks/Rust/axum/src/sqlx/database.rs @@ -0,0 +1,36 @@ +use std::io; + +use sqlx::{postgres::PgPoolOptions, PgPool}; + +#[derive(Debug)] +#[allow(dead_code)] +pub enum PgError { + Io(io::Error), + Pg(sqlx::Error), +} + +impl From for PgError { + fn from(err: io::Error) -> Self { + PgError::Io(err) + } +} + +impl From for PgError { + fn from(err: sqlx::Error) -> Self { + PgError::Pg(err) + } +} + +pub async fn create_pool( + database_url: String, + max_pool_size: u32, + min_pool_size: u32, +) -> PgPool { + PgPoolOptions::new() + .max_connections(max_pool_size) + .min_connections(min_pool_size) + .test_before_acquire(false) + .connect(&database_url) + .await + .unwrap() +} diff --git a/frameworks/Rust/axum/src/sqlx/mod.rs b/frameworks/Rust/axum/src/sqlx/mod.rs new file mode 100644 index 00000000000..c51e02d23d3 --- /dev/null +++ b/frameworks/Rust/axum/src/sqlx/mod.rs @@ -0,0 +1,2 @@ +pub mod database; +pub mod models; diff --git a/frameworks/Rust/axum/src/models_sqlx.rs b/frameworks/Rust/axum/src/sqlx/models.rs similarity index 100% rename from frameworks/Rust/axum/src/models_sqlx.rs rename to frameworks/Rust/axum/src/sqlx/models.rs From a05b90e347cd3b8b29f1331c198e133b8600477d Mon Sep 17 00:00:00 2001 From: Ishtmeet Singh Date: Wed, 4 Sep 2024 01:22:48 +0530 Subject: [PATCH 21/40] Bumps version (#9241) --- frameworks/JavaScript/velocy/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/velocy/package.json b/frameworks/JavaScript/velocy/package.json index a51441b5c26..320f6058e7a 100644 --- a/frameworks/JavaScript/velocy/package.json +++ b/frameworks/JavaScript/velocy/package.json @@ -1,5 +1,5 @@ { "dependencies": { - "velocy": "0.0.13" + "velocy": "0.0.14" } } From 902efb7223f1243beada2f4d2d9bfcd4d6e9bd04 Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Wed, 4 Sep 2024 03:53:11 +0800 Subject: [PATCH 22/40] [xitca-web] bug fix (#9243) * [xitca-web] bug fix * dep update. * template fix --- frameworks/Rust/xitca-web/Cargo.lock | 58 +++++++++---------- frameworks/Rust/xitca-web/Cargo.toml | 18 +++--- frameworks/Rust/xitca-web/src/db.rs | 4 +- .../Rust/xitca-web/templates/fortune.stpl | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 01bd80ec5e3..1f1f0e18a74 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -149,9 +149,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.13" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "shlex", ] @@ -218,9 +218,9 @@ dependencies = [ [[package]] name = "diesel" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf97ee7261bb708fa3402fa9c17a54b70e90e3cb98afb3dc8999d5512cb03f94" +checksum = "65e13bab2796f412722112327f3e575601a3e9cdcbe426f0d30dbf43f3f5dc71" dependencies = [ "bitflags 2.6.0", "byteorder", @@ -232,9 +232,9 @@ dependencies = [ [[package]] name = "diesel_derives" -version = "2.2.2" +version = "2.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ff2be1e7312c858b2ef974f5c7089833ae57b5311b334b30923af58e5718d8" +checksum = "e7f2c3de51e2ba6bf2a648285696137aaf0f5f487bcbea93972fe8a364e131a4" dependencies = [ "diesel_table_macro_syntax", "dsl_auto_type", @@ -291,9 +291,9 @@ checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", @@ -589,9 +589,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -721,9 +721,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -798,9 +798,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "sailfish" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd5f4680149b62b3478f6af08a8f1c37794bc1bc577e28874a4d0c70084d600" +checksum = "d4d5cd6d4f24f3ab107e949ab424738cf55b03deddce3b184c46985d7b1394ef" dependencies = [ "itoap", "ryu", @@ -810,9 +810,9 @@ dependencies = [ [[package]] name = "sailfish-compiler" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67087aca4a3886686a88cee6835089c53e6143a0b8c5be01e63e4fe2f6dfe7cb" +checksum = "7254ec7b3651f7f723a9073153f5dcddc1f2bf1bf8d1b23ac71c236ef6360d2b" dependencies = [ "filetime", "home", @@ -824,9 +824,9 @@ dependencies = [ [[package]] name = "sailfish-macros" -version = "0.8.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47e31910c5f9230e99992568d05a5968fe4f42a635c3f912c993e9f66a619a5" +checksum = "00812289fe1891c191cc2d9db461352fc410619e07ec2bb748faaa06412619d0" dependencies = [ "proc-macro2", "sailfish-compiler", @@ -849,18 +849,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", @@ -869,9 +869,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", "memchr", @@ -987,9 +987,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1025,9 +1025,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "libc", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=f4e7bed#f4e7bedfb441897d1f26a6e4d8cbfada23953269" +source = "git+https://github.com/HFQR/xitca-web.git?rev=6870448#687044829f0e89bab3efafcf7fb53e53167ad32c" dependencies = [ "fallible-iterator", "percent-encoding", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index e4614eb0bab..84eb12264b3 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -30,25 +30,25 @@ required-features = ["pg-orm", "template", "web-codegen"] [features] # pg optional -pg = ["xitca-postgres/single-thread"] +pg = ["dep:xitca-postgres"] # pg send/sync optional -pg-sync = ["xitca-postgres"] +pg-sync = ["dep:xitca-postgres"] # pg orm optional -pg-orm = ["diesel"] +pg-orm = ["dep:diesel"] # http router optional router = ["xitca-http/router"] # web optional -web = ["xitca-web"] +web = ["dep:xitca-web"] # web codegen optional web-codegen = ["xitca-web/codegen", "xitca-web/urlencoded"] # template optional -template = ["sailfish"] +template = ["dep:sailfish"] # io-uring optional io-uring = ["xitca-http/io-uring", "xitca-server/io-uring"] # axum optional -axum = ["dep:axum", "http-body", "tower", "tower-http", "xitca-web/tower-http-compat" ] +axum = ["dep:axum", "dep:http-body", "dep:tower", "dep:tower-http", "xitca-web/tower-http-compat" ] # unrealistic performance optimization -perf = ["mimalloc", "tokio/parking_lot"] +perf = ["dep:mimalloc", "tokio/parking_lot"] [dependencies] xitca-http = "0.6" @@ -71,7 +71,7 @@ xitca-postgres = { version = "0.1", optional = true } diesel = { version = "2", features = ["postgres", "r2d2"], optional = true } # template optional -sailfish = { version = "0.8", default-features = false, features = ["derive", "perf-inline"], optional = true } +sailfish = { version = "0.9", default-features = false, features = ["derive", "perf-inline"], optional = true } # axum optional axum = { version = "0.7", optional = true, default-features = false, features = ["json", "query"] } @@ -95,5 +95,5 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "f4e7bed" } +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "6870448" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index aa783e29dce..276eb93ec9e 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -100,7 +100,7 @@ impl Client { let mut res = { let (ref mut rng, ref mut buf) = *self.shared(); - let mut pipe = Pipeline::<_, false>::with_capacity_from_buf(len, buf); + let mut pipe = Pipeline::with_capacity_from_buf(len, buf); (0..num).try_for_each(|_| pipe.query_raw(&self.world, [rng.gen_id()]))?; @@ -128,7 +128,7 @@ impl Client { let mut res = { let (ref mut rng, ref mut buf) = *self.shared(); - let mut pipe = Pipeline::<_, false>::with_capacity_from_buf(len + 1, buf); + let mut pipe = Pipeline::with_capacity_from_buf(len + 1, buf); (0..num).try_for_each(|_| { let w_id = rng.gen_id(); diff --git a/frameworks/Rust/xitca-web/templates/fortune.stpl b/frameworks/Rust/xitca-web/templates/fortune.stpl index eb1abe6a4fa..28227945b4c 100644 --- a/frameworks/Rust/xitca-web/templates/fortune.stpl +++ b/frameworks/Rust/xitca-web/templates/fortune.stpl @@ -4,7 +4,7 @@ - <% for item in items { %><% } %> + <% for item in self.items { %><% } %>
idmessage
<%= item.id %><%= &*item.message %>
<%= item.id %><%= &*item.message %>
\ No newline at end of file From d62e690f2a9109f3dd8465704eafd35f933fc4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E4=B8=9C?= Date: Wed, 4 Sep 2024 03:53:44 +0800 Subject: [PATCH 23/40] Update Solon Jdk To 21 (#9245) * Update Solon Version To 2.9.1 * Update Solon Version To 2.9.1 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 --- frameworks/Java/solon/README.md | 8 +-- frameworks/Java/solon/pom.xml | 63 ++++--------------- frameworks/Java/solon/solon.dockerfile | 8 +-- .../src/main/java/{pmg => hello}/Main.java | 26 ++++---- .../controller/HelloController.java | 4 +- .../java/{pmg => hello}/model/Message.java | 2 +- 6 files changed, 35 insertions(+), 76 deletions(-) rename frameworks/Java/solon/src/main/java/{pmg => hello}/Main.java (87%) rename frameworks/Java/solon/src/main/java/{pmg => hello}/controller/HelloController.java (88%) rename frameworks/Java/solon/src/main/java/{pmg => hello}/model/Message.java (93%) diff --git a/frameworks/Java/solon/README.md b/frameworks/Java/solon/README.md index 0824b5effd9..f2370ab2305 100644 --- a/frameworks/Java/solon/README.md +++ b/frameworks/Java/solon/README.md @@ -4,13 +4,13 @@ This is the solon portion of a [benchmarking test suite](../) comparing a variety of web development platforms. ### JSON Encoding Test -* [JSON test source](src/main/java/pmg/Main.java) -* [Plaintext test source](src/main/java/pmg/Main.java) +* [JSON test source](src/main/java/hello/Main.java) +* [Plaintext test source](src/main/java/hello/Main.java) ## Versions -* [Java OpenJDK 1.8](http://openjdk.java.net/) -* [solon 2.0.0](https://github.com/noear/solon) +* [Java OpenJDK 21](http://openjdk.java.net/) +* [solon 2.9.1](https://github.com/noear/solon) ## Test URLs diff --git a/frameworks/Java/solon/pom.xml b/frameworks/Java/solon/pom.xml index df69e436229..a9568927908 100644 --- a/frameworks/Java/solon/pom.xml +++ b/frameworks/Java/solon/pom.xml @@ -2,15 +2,19 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - org.noear.solon - solon-benchmark + + org.noear + solon-parent + 2.9.1 + + + hello + hello-solon 1.0 jar - UTF-8 - 11 - 2.9.1 + 21 @@ -19,6 +23,7 @@ solon.boot.smarthttp ${solon.version} + org.noear solon.serialization.snack3 @@ -26,66 +31,20 @@ - - - central - Central Repository - https://repo.maven.apache.org/maven2 - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - - - - - central - Central Repository - https://repo.maven.apache.org/maven2 - - - sonatype-nexus-snapshots - Sonatype Nexus Snapshots - https://oss.sonatype.org/content/repositories/snapshots - - false - - - true - - - - ${project.artifactId} - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - -parameters - ${java.vertsion} - ${java.vertsion} - UTF-8 - false - - - org.apache.maven.plugins maven-assembly-plugin - 3.6.0 jar-with-dependencies - pmg.Main + hello.Main diff --git a/frameworks/Java/solon/solon.dockerfile b/frameworks/Java/solon/solon.dockerfile index 21d7f50d8a8..c387938661c 100644 --- a/frameworks/Java/solon/solon.dockerfile +++ b/frameworks/Java/solon/solon.dockerfile @@ -1,13 +1,13 @@ -FROM maven:3.6.1-jdk-11-slim as maven +FROM maven:3.9.7-amazoncorretto-21 as maven WORKDIR /solon COPY pom.xml pom.xml COPY src src RUN mvn compile assembly:single -q -FROM openjdk:11.0.3-jdk-slim +FROM openjdk:21-jdk-slim WORKDIR /solon -COPY --from=maven /solon/target/solon-benchmark-jar-with-dependencies.jar app.jar +COPY --from=maven /solon/target/hello-solon.jar app.jar EXPOSE 8080 -CMD ["java", "-server", "-XX:+UseNUMA", "-XX:+UseParallelGC", "-XX:+AggressiveOpts", "-cp", "app.jar", "pmg.Main"] +CMD ["java", "-server", "-cp", "app.jar", "hello.Main"] \ No newline at end of file diff --git a/frameworks/Java/solon/src/main/java/pmg/Main.java b/frameworks/Java/solon/src/main/java/hello/Main.java similarity index 87% rename from frameworks/Java/solon/src/main/java/pmg/Main.java rename to frameworks/Java/solon/src/main/java/hello/Main.java index b4b7b651797..0746f86be45 100644 --- a/frameworks/Java/solon/src/main/java/pmg/Main.java +++ b/frameworks/Java/solon/src/main/java/hello/Main.java @@ -1,13 +1,13 @@ -package pmg; - -import org.noear.solon.Solon; - -/** - * @author pmg1991 - * @version V1.0 - */ -public class Main { - public static void main(String[] args) { - Solon.start(Main.class, args); - } -} +package hello; + +import org.noear.solon.Solon; + +/** + * @author pmg1991 + * @version V1.0 + */ +public class Main { + public static void main(String[] args) { + Solon.start(Main.class, args); + } +} diff --git a/frameworks/Java/solon/src/main/java/pmg/controller/HelloController.java b/frameworks/Java/solon/src/main/java/hello/controller/HelloController.java similarity index 88% rename from frameworks/Java/solon/src/main/java/pmg/controller/HelloController.java rename to frameworks/Java/solon/src/main/java/hello/controller/HelloController.java index fe9a1b43e3a..77049043e97 100644 --- a/frameworks/Java/solon/src/main/java/pmg/controller/HelloController.java +++ b/frameworks/Java/solon/src/main/java/hello/controller/HelloController.java @@ -1,9 +1,9 @@ -package pmg.controller; +package hello.controller; import org.noear.solon.annotation.Controller; import org.noear.solon.annotation.Get; import org.noear.solon.annotation.Mapping; -import pmg.model.Message; +import hello.model.Message; /** * @author noear diff --git a/frameworks/Java/solon/src/main/java/pmg/model/Message.java b/frameworks/Java/solon/src/main/java/hello/model/Message.java similarity index 93% rename from frameworks/Java/solon/src/main/java/pmg/model/Message.java rename to frameworks/Java/solon/src/main/java/hello/model/Message.java index f88b9b1a8d4..1df5276ca8d 100644 --- a/frameworks/Java/solon/src/main/java/pmg/model/Message.java +++ b/frameworks/Java/solon/src/main/java/hello/model/Message.java @@ -1,4 +1,4 @@ -package pmg.model; +package hello.model; /** * @author pmg1991 From 9ae18ac38774bb48ea9a6eacd0454a79d1a5c9cc Mon Sep 17 00:00:00 2001 From: Vladimir Shchur Date: Tue, 3 Sep 2024 22:54:16 +0300 Subject: [PATCH 24/40] [F#/Oxpecker] Improvements for json and fortunes benchmarks (#9246) * [F#/Oxpecker] Improved fortunes rendering * [F#/Oxpecker] Use SpanJson for json benchmark --- frameworks/FSharp/oxpecker/README.md | 2 +- frameworks/FSharp/oxpecker/src/App/App.fsproj | 2 ++ frameworks/FSharp/oxpecker/src/App/Program.fs | 22 +++++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/frameworks/FSharp/oxpecker/README.md b/frameworks/FSharp/oxpecker/README.md index 3d8a00a248a..a35cbf08522 100644 --- a/frameworks/FSharp/oxpecker/README.md +++ b/frameworks/FSharp/oxpecker/README.md @@ -19,5 +19,5 @@ This includes tests for plaintext, json, fortunes, single query, mutliple querie * [Oxpecker](https://github.com/Lanayx/Oxpecker) * [Npgsql](https://github.com/npgsql/npgsql) -* [System.Text.Json](https://github.com/dotnet/runtime/tree/main/src/libraries/System.Text.Json) +* [SpanJson](https://github.com/Tornhoof/SpanJson) * ASP.NET Core \ 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 35df8d5c493..e9aa702a5a1 100644 --- a/frameworks/FSharp/oxpecker/src/App/App.fsproj +++ b/frameworks/FSharp/oxpecker/src/App/App.fsproj @@ -15,6 +15,8 @@ + + \ No newline at end of file diff --git a/frameworks/FSharp/oxpecker/src/App/Program.fs b/frameworks/FSharp/oxpecker/src/App/Program.fs index ea6bc66b911..895c54c9693 100644 --- a/frameworks/FSharp/oxpecker/src/App/Program.fs +++ b/frameworks/FSharp/oxpecker/src/App/Program.fs @@ -2,6 +2,7 @@ namespace App open System open Oxpecker +open System.Runtime.InteropServices [] module HtmlViews = @@ -26,21 +27,20 @@ module HtmlViews = ) |> RenderHelpers.prerender let fortunes (fortunesData: ResizeArray) = - RenderHelpers.combine head tail ( - __() { - for fortune in fortunesData do - tr() { - td() { raw <| string fortune.id } - td() { fortune.message } - } + let fragment = __() + for fortune in CollectionsMarshal.AsSpan fortunesData do + tr() { + td() { raw <| string fortune.id } + td() { fortune.message } } - ) + |> fragment.AddChild + RenderHelpers.combine head tail fragment [] module HttpHandlers = open System.Text open Microsoft.AspNetCore.Http - open System.Text.Json + open SpanJson let private extra = { @@ -98,9 +98,9 @@ module HttpHandlers = ctx.WriteBytes(result) let jsonSimple value : EndpointHandler = - let options = JsonSerializerOptions(JsonSerializerDefaults.Web) fun ctx -> - ctx.Response.WriteAsJsonAsync(value, options) + ctx.SetContentType("application/json") + JsonSerializer.Generic.Utf8.SerializeAsync<_>(value, stream = ctx.Response.Body).AsTask() let endpoints = [| From f7a663eaf6b46d90f0b2541334cb1da72e2cd259 Mon Sep 17 00:00:00 2001 From: kanarus Date: Wed, 4 Sep 2024 04:54:40 +0900 Subject: [PATCH 25/40] bunp ohkami to v0.20, deps & refactor some (#9247) --- frameworks/Rust/ohkami/Cargo.lock | 565 ++++++++++++----------- frameworks/Rust/ohkami/Cargo.toml | 19 +- frameworks/Rust/ohkami/ohkami.dockerfile | 2 +- frameworks/Rust/ohkami/src/fangs.rs | 39 -- frameworks/Rust/ohkami/src/main.rs | 36 +- frameworks/Rust/ohkami/src/models.rs | 9 +- frameworks/Rust/ohkami/src/postgres.rs | 29 +- 7 files changed, 363 insertions(+), 336 deletions(-) diff --git a/frameworks/Rust/ohkami/Cargo.lock b/frameworks/Rust/ohkami/Cargo.lock index 95d46009a5b..e379d121817 100644 --- a/frameworks/Rust/ohkami/Cargo.lock +++ b/frameworks/Rust/ohkami/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -24,7 +24,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom", "once_cell", "version_check", "zerocopy", @@ -66,15 +65,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -87,9 +86,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.7" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -105,9 +104,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -123,9 +122,9 @@ dependencies = [ [[package]] name = "byte_reader" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac67f5455e694831246ed9a2d62c98dbb7586281dcfaba6621888ac9b576df" +checksum = "3aad623c0c9416ec94524edd23af3f3e2fd16d1ec7d41c940084c05f77e35c96" [[package]] name = "byteorder" @@ -135,15 +134,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.95" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -151,6 +153,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -175,15 +186,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" dependencies = [ "libc", ] @@ -214,9 +225,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -241,15 +252,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] @@ -278,9 +289,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "either" -version = "1.11.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" dependencies = [ "serde", ] @@ -293,9 +304,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -314,21 +325,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" - -[[package]] -name = "finl_unicode" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "flume" @@ -338,7 +348,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -417,7 +427,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] @@ -461,9 +471,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -472,15 +482,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", @@ -488,21 +498,18 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.8.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ "hashbrown", ] [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -dependencies = [ - "unicode-segmentation", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -555,23 +562,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itoa" version = "1.0.11" @@ -580,18 +578,18 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] name = "libc" -version = "0.2.153" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" @@ -601,9 +599,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libsqlite3-sys" -version = "0.27.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" dependencies = [ "cc", "pkg-config", @@ -612,15 +610,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -628,9 +626,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "md-5" @@ -644,9 +642,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" @@ -656,31 +654,31 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -730,9 +728,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -741,38 +739,28 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" -version = "0.32.2" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] [[package]] name = "ohkami" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e598d3d323527b920e159d55da2754067a5edfbc0678d60b3886fc379f4637f2" +checksum = "aa5507d0f2230d8fbbec9163207da1219ac513441269465a8d532e0bf5018411" dependencies = [ "byte_reader", "hmac", @@ -787,7 +775,7 @@ dependencies = [ [[package]] name = "ohkami_framework_benchmarks" -version = "0.19.0" +version = "0.20.0" dependencies = [ "futures-util", "ohkami", @@ -799,9 +787,9 @@ dependencies = [ [[package]] name = "ohkami_lib" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05fdeee00f86ee850c63a15068f2c2a3aeb6d707d4936f2261ec0e70ff48704b" +checksum = "889b290a5ca6f0e2d1b1bae72d0ec1fb768d84cf246c532e6f7c65ff962e65e3" dependencies = [ "byte_reader", "percent-encoding", @@ -810,9 +798,9 @@ dependencies = [ [[package]] name = "ohkami_macros" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fa46d8805dede76dce71f8725d48d655f74e2c702824f7a785257d1cc4dd1b" +checksum = "8a231d9afdadeab9fc5c850093377c65ecd30512692de0efec51f708dff5be12" dependencies = [ "proc-macro2", "quote", @@ -827,11 +815,11 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -848,7 +836,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] @@ -859,9 +847,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -869,11 +857,17 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -881,22 +875,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem-rfc7468" @@ -954,9 +948,12 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "prettyplease" @@ -970,18 +967,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1025,11 +1022,20 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "regex" -version = "1.10.4" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1039,9 +1045,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1050,9 +1056,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rsa" @@ -1076,32 +1082,32 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1110,9 +1116,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" @@ -1131,11 +1137,11 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -1144,9 +1150,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -1154,36 +1160,49 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.198" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.127" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ + "form_urlencoded", "itoa", "ryu", "serde", @@ -1211,6 +1230,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.2" @@ -1244,23 +1269,20 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -1282,20 +1304,19 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" dependencies = [ - "itertools", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" +checksum = "fcfa89bea9500db4a0d038513d7a060566bfc51d46d1c014847049a45cce85e8" dependencies = [ "sqlx-core", "sqlx-macros", @@ -1306,11 +1327,10 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" +checksum = "d06e2f2bd861719b1f3f0c7dbe1d80c30bf59e76cf019f07d9014ed7eefb8e08" dependencies = [ - "ahash", "atoi", "byteorder", "bytes", @@ -1323,6 +1343,7 @@ dependencies = [ "futures-intrusive", "futures-io", "futures-util", + "hashbrown", "hashlink", "hex", "indexmap", @@ -1346,22 +1367,22 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" +checksum = "2f998a9defdbd48ed005a89362bd40dd2117502f15294f61c8d47034107dbbdc" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "sqlx-macros-core" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" +checksum = "3d100558134176a2629d46cec0c8891ba0be8910f7896abfdb75ef4ab6f4e7ce" dependencies = [ "dotenvy", "either", @@ -1377,7 +1398,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 1.0.109", + "syn 2.0.77", "tempfile", "tokio", "url", @@ -1385,13 +1406,13 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" +checksum = "936cac0ab331b14cb3921c62156d913e4c15b74fb6ec0f3146bd4ef6e4fb3c12" dependencies = [ "atoi", "base64", - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "bytes", "crc", @@ -1427,13 +1448,13 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" +checksum = "9734dbce698c67ecf67c442f768a5e90a49b2a4d61a9f1d59f73874bd4cf0710" dependencies = [ "atoi", "base64", - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "crc", "dotenvy", @@ -1465,9 +1486,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" +checksum = "a75b419c3c1b1697833dd927bdc4c6545a620bc1bbafabd44e1efbe9afcd337e" dependencies = [ "atoi", "flume", @@ -1480,28 +1501,28 @@ dependencies = [ "log", "percent-encoding", "serde", + "serde_urlencoded", "sqlx-core", "tracing", "url", - "urlencoding", ] [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -1516,9 +1537,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.60" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1527,41 +1548,42 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -1574,32 +1596,31 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.38.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] @@ -1642,7 +1663,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] @@ -1682,22 +1703,22 @@ dependencies = [ ] [[package]] -name = "unicode-segmentation" -version = "1.11.0" +name = "unicode-properties" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "unicode_categories" @@ -1707,21 +1728,15 @@ checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - [[package]] name = "v_eval" version = "0.6.0" @@ -1746,9 +1761,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1768,7 +1783,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" dependencies = [ - "redox_syscall", + "redox_syscall 0.4.1", "wasite", ] @@ -1809,7 +1824,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1829,18 +1853,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1851,9 +1875,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1863,9 +1887,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1875,15 +1899,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1893,9 +1917,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1905,9 +1929,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1917,9 +1941,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1929,9 +1953,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "yansi-term" @@ -2029,26 +2053,27 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.60", + "syn 2.0.77", ] [[package]] name = "zeroize" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63381fa6624bf92130a6b87c0d07380116f80b565c42cf0d754136f0238359ef" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/frameworks/Rust/ohkami/Cargo.toml b/frameworks/Rust/ohkami/Cargo.toml index b6bf50cf97c..04e08b92b0c 100644 --- a/frameworks/Rust/ohkami/Cargo.toml +++ b/frameworks/Rust/ohkami/Cargo.toml @@ -1,13 +1,24 @@ [package] name = "ohkami_framework_benchmarks" -version = "0.19.0" +version = "0.20.0" edition = "2021" authors = ["kanarus "] [dependencies] -ohkami = { version = "=0.19.0", features = ["rt_tokio"] } -tokio = { version = "1.38.0" , features = ["full"] } +ohkami = { version = "=0.20.0", features = ["rt_tokio"] } +tokio = { version = "1.40.0" , features = ["full"] } rand = { version = "0.8.5" , features = ["small_rng"] } -sqlx = { version = "0.7.4" , features = ["postgres", "macros", "runtime-tokio-native-tls"] } +sqlx = { version = "0.8.1" , features = ["postgres", "macros", "runtime-tokio-native-tls"] } yarte = { version = "0.15.7" } futures-util = { version = "0.3.30" } + +[profile.release] +opt-level = 3 +debug = false +debug-assertions = false +lto = true +panic = "abort" +incremental = false +codegen-units = 1 +rpath = false +strip = false \ No newline at end of file diff --git a/frameworks/Rust/ohkami/ohkami.dockerfile b/frameworks/Rust/ohkami/ohkami.dockerfile index b993ec905a5..287f293a061 100644 --- a/frameworks/Rust/ohkami/ohkami.dockerfile +++ b/frameworks/Rust/ohkami/ohkami.dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.79-slim-buster +FROM rust:1.80-slim-bullseye WORKDIR /ohkami_framework_benchmarks ENV DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world diff --git a/frameworks/Rust/ohkami/src/fangs.rs b/frameworks/Rust/ohkami/src/fangs.rs index 46a19808f46..2dd8e27e5d3 100644 --- a/frameworks/Rust/ohkami/src/fangs.rs +++ b/frameworks/Rust/ohkami/src/fangs.rs @@ -1,5 +1,4 @@ use ohkami::prelude::*; -use crate::Postgres; #[derive(Clone)] @@ -10,41 +9,3 @@ impl FangAction for SetServer { res.headers.set().Server("ohkami"); } } - -impl Postgres { - pub async fn init() -> impl FangAction { - #[derive(Clone)] - pub struct UsePostgres(Postgres); - impl FangAction for UsePostgres { - #[inline(always)] - async fn fore<'a>(&'a self, req: &'a mut Request) -> Result<(), Response> { - Ok(req.memorize(self.0.clone())) - } - } - - macro_rules! load_env { - ($($name:ident as $t:ty)*) => {$( - #[allow(non_snake_case)] - let $name = ::std::env::var(stringify!($name)) - .expect(concat!( - "Failed to load environment variable ", - "`", stringify!($name), "`" - )) - .parse::<$t>() - .unwrap(); - )*}; - } load_env! { - MAX_CONNECTIONS as u32 - MIN_CONNECTIONS as u32 - DATABASE_URL as String - } - - let pool = sqlx::postgres::PgPoolOptions::new() - .max_connections(MAX_CONNECTIONS) - .min_connections(MIN_CONNECTIONS) - .connect(&DATABASE_URL).await - .unwrap(); - - UsePostgres(pool.into()) - } -} diff --git a/frameworks/Rust/ohkami/src/main.rs b/frameworks/Rust/ohkami/src/main.rs index 7473338dc5b..96cc9cc2fbc 100644 --- a/frameworks/Rust/ohkami/src/main.rs +++ b/frameworks/Rust/ohkami/src/main.rs @@ -11,12 +11,16 @@ mod templates; use templates::FortunesTemplate; use ohkami::prelude::*; +use ohkami::format::{JSON, Query}; use ohkami::Memory; #[tokio::main] async fn main() { - Ohkami::with((SetServer, Postgres::init().await), ( + Ohkami::with(( + SetServer, + Memory::new(Postgres::new().await), + ), ( "/json" .GET(json_serialization), "/db" .GET(single_database_query), "/queries" .GET(multiple_database_query), @@ -26,40 +30,44 @@ async fn main() { )).howl("0.0.0.0:8000").await } -async fn json_serialization() -> Message { - Message { +async fn json_serialization() -> JSON { + JSON(Message { message: "Hello, World!" - } + }) } -async fn single_database_query(p: Memory<'_, Postgres>) -> World { - p.select_random_world().await +async fn single_database_query(p: Memory<'_, Postgres>) -> JSON { + let world = p.select_random_world().await; + JSON(world) } -async fn multiple_database_query(q: WorldsQuery<'_>, p: Memory<'_, Postgres>) -> Vec { +async fn multiple_database_query( + Query(q): Query>, + p: Memory<'_, Postgres> +) -> JSON> { let n = q.parse(); - p.select_n_random_worlds(n).await + let worlds = p.select_n_random_worlds(n).await; + JSON(worlds) } async fn fortunes(p: Memory<'_, Postgres>) -> FortunesTemplate { let mut fortunes = p.select_all_fortunes().await; - fortunes.push(Fortune { id: 0, message: String::from("Additional fortune added at request time."), }); fortunes.sort_unstable_by(|a, b| str::cmp(&a.message, &b.message)); - FortunesTemplate { fortunes } } -async fn database_updates(q: WorldsQuery<'_>, p: Memory<'_, Postgres>) -> Vec { +async fn database_updates( + Query(q): Query>, + p: Memory<'_, Postgres> +) -> JSON> { let n = q.parse(); let mut worlds = p.select_n_random_worlds(n).await; - p.update_random_ids_of_worlds(&mut worlds).await; - - worlds + JSON(worlds) } async fn plaintext() -> &'static str { diff --git a/frameworks/Rust/ohkami/src/models.rs b/frameworks/Rust/ohkami/src/models.rs index 55eb8f8fa6d..874dd22a5d7 100644 --- a/frameworks/Rust/ohkami/src/models.rs +++ b/frameworks/Rust/ohkami/src/models.rs @@ -1,8 +1,7 @@ -use ohkami::typed::{Payload, Query}; -use ohkami::builtin::payload::JSON; +use ohkami::serde::{Serialize, Deserialize}; -#[Payload(JSON/S)] +#[derive(Serialize)] pub struct Message { pub message: &'static str, } @@ -14,14 +13,14 @@ pub struct Fortune { } #[derive(sqlx::FromRow)] -#[Payload(JSON/S)] +#[derive(Serialize)] pub struct World { pub id: i32, #[serde(rename="randomNumber")] pub randomnumber: i32, } -#[Query] +#[derive(Deserialize)] pub struct WorldsQuery<'q> { q: Option<&'q str>, } diff --git a/frameworks/Rust/ohkami/src/postgres.rs b/frameworks/Rust/ohkami/src/postgres.rs index e9238d67493..c320e2516e3 100644 --- a/frameworks/Rust/ohkami/src/postgres.rs +++ b/frameworks/Rust/ohkami/src/postgres.rs @@ -6,9 +6,32 @@ use crate::models::{World, Fortune}; #[derive(Clone)] pub struct Postgres(sqlx::PgPool); -impl From for Postgres { - fn from(pgpool: sqlx::PgPool) -> Self { - Self(pgpool) +impl Postgres { + pub async fn new() -> Self { + macro_rules! load_env { + ($($name:ident as $t:ty)*) => {$( + #[allow(non_snake_case)] + let $name = ::std::env::var(stringify!($name)) + .expect(concat!( + "Failed to load environment variable ", + "`", stringify!($name), "`" + )) + .parse::<$t>() + .unwrap(); + )*}; + } load_env! { + MAX_CONNECTIONS as u32 + MIN_CONNECTIONS as u32 + DATABASE_URL as String + } + + let pool = sqlx::postgres::PgPoolOptions::new() + .max_connections(MAX_CONNECTIONS) + .min_connections(MIN_CONNECTIONS) + .connect(&DATABASE_URL).await + .unwrap(); + + Self(pool) } } From 96d08a74c0b2e1392ad60c328a94f7c23e489f60 Mon Sep 17 00:00:00 2001 From: cclilshy Date: Wed, 4 Sep 2024 04:35:23 +0800 Subject: [PATCH 26/40] [PHP/laravel] Add PRipple coroutine engine for Laravel framework (#9239) * [PHP/laravel] Add PRipple coroutine engine for Laravel framework * Style: Normalized code style & display_name adjustment --- frameworks/PHP/laravel/benchmark_config.json | 25 +++++++++- .../PHP/laravel/laravel-pripple.dockerfile | 48 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 frameworks/PHP/laravel/laravel-pripple.dockerfile diff --git a/frameworks/PHP/laravel/benchmark_config.json b/frameworks/PHP/laravel/benchmark_config.json index 588dab1e17f..f8421378e51 100644 --- a/frameworks/PHP/laravel/benchmark_config.json +++ b/frameworks/PHP/laravel/benchmark_config.json @@ -138,6 +138,29 @@ "display_name": "laravel-octane [frankenphp]", "notes": "", "versus": "php" + }, + "pripple": { + "json_url": "/json", + "db_url": "/db", + "query_url": "/queries/", + "fortune_url": "/fortunes", + "update_url": "/updates/", + "plaintext_url": "/plaintext", + "port": 8080, + "approach": "Realistic", + "classification": "Fullstack", + "database": "MySQL", + "framework": "laravel", + "language": "PHP", + "flavor": "PHP8.3", + "orm": "Full", + "platform": "PRipple", + "webserver": "PServer", + "os": "Linux", + "database_os": "Linux", + "display_name": "laravel-pripple", + "notes": "", + "versus": "php" } }] -} \ No newline at end of file +} diff --git a/frameworks/PHP/laravel/laravel-pripple.dockerfile b/frameworks/PHP/laravel/laravel-pripple.dockerfile new file mode 100644 index 00000000000..869661a0432 --- /dev/null +++ b/frameworks/PHP/laravel/laravel-pripple.dockerfile @@ -0,0 +1,48 @@ +FROM php:8.3-cli + +RUN apt-get update -yqq >> /dev/null +RUN apt-get install -y libevent-dev \ + libssl-dev \ + pkg-config \ + build-essential \ + unzip >> /dev/null + +RUN docker-php-ext-install pdo_mysql \ + opcache \ + posix \ + pcntl \ + sockets >> /dev/null + +RUN pecl install event >> /dev/null + +RUN docker-php-ext-enable pdo_mysql opcache posix pcntl sockets +RUN docker-php-ext-enable --ini-name zz-event.ini event +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 + +COPY --from=composer --link /usr/bin/composer /usr/local/bin/composer + +# Initialize +WORKDIR /laravel +COPY --link . . + +RUN mkdir -p bootstrap/cache \ + storage/logs \ + storage/framework/sessions \ + storage/framework/views \ + storage/framework/cache + +# Configure +RUN echo "PRP_HTTP_LISTEN=http://0.0.0.0:8080" >> .env +RUN echo "PRP_HTTP_COUNT=64" >> .env + +RUN composer install --quiet +RUN php artisan optimize + +RUN composer require cclilshy/p-ripple-drive --quiet +RUN composer update --quiet + +EXPOSE 8080 + +ENTRYPOINT ["php","artisan","p:server","start"] From f83474331848fc9bb33426c1fd3b18c6fe118701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Wed, 4 Sep 2024 19:00:23 +0200 Subject: [PATCH 27/40] Optimize Spring samples (#9249) * Optimize spring-webflux - Upgrade to Spring Boot 3.3.3 - Optimize handler implementations - Optimize the router implementation - Use WebFlux.fn configuration for HttpHandler * Optimize spring - Upgrade to Spring Boot 3.3.3 - Use WebMVC.fn instead of `@Controller` - Refine configuration --- frameworks/Java/spring-webflux/pom.xml | 2 +- .../src/main/java/benchmark/App.java | 17 ++++ .../{WebfluxHandler.java => DbHandler.java} | 32 ++----- .../main/java/benchmark/web/JsonHandler.java | 54 ++++++++++++ .../benchmark/{ => web}/ServerFilter.java | 5 +- .../main/java/benchmark/web/TextHandler.java | 37 +++++++++ .../java/benchmark/web/WebfluxRouter.java | 29 ++++--- frameworks/Java/spring/pom.xml | 2 +- frameworks/Java/spring/spring.dockerfile | 2 +- .../Java/spring/src/main/java/hello/App.java | 3 +- .../java/hello/UpdateWorldServiceImpl.java | 5 +- .../DbHandler.java} | 83 ++++++++----------- .../src/main/java/hello/web/JsonHandler.java | 39 +++++++++ .../src/main/java/hello/web/TextHandler.java | 27 ++++++ .../src/main/java/hello/web/WebmvcRouter.java | 32 +++++++ .../spring/src/main/resources/application.yml | 9 +- 16 files changed, 281 insertions(+), 97 deletions(-) rename frameworks/Java/spring-webflux/src/main/java/benchmark/web/{WebfluxHandler.java => DbHandler.java} (74%) create mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/web/JsonHandler.java rename frameworks/Java/spring-webflux/src/main/java/benchmark/{ => web}/ServerFilter.java (83%) create mode 100644 frameworks/Java/spring-webflux/src/main/java/benchmark/web/TextHandler.java rename frameworks/Java/spring/src/main/java/hello/{controller/HelloController.java => web/DbHandler.java} (50%) create mode 100644 frameworks/Java/spring/src/main/java/hello/web/JsonHandler.java create mode 100644 frameworks/Java/spring/src/main/java/hello/web/TextHandler.java create mode 100644 frameworks/Java/spring/src/main/java/hello/web/WebmvcRouter.java diff --git a/frameworks/Java/spring-webflux/pom.xml b/frameworks/Java/spring-webflux/pom.xml index 4dd5b09698c..c15b211c92d 100644 --- a/frameworks/Java/spring-webflux/pom.xml +++ b/frameworks/Java/spring-webflux/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.1 + 3.3.3 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 37ff0a80ff0..c574863a9a9 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/App.java @@ -1,13 +1,30 @@ package benchmark; +import benchmark.web.ServerFilter; + import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.http.server.reactive.HttpHandler; import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.web.reactive.function.server.HandlerStrategies; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.server.WebHandler; +import org.springframework.web.server.adapter.WebHttpHandlerBuilder; @SpringBootApplication @EnableScheduling public class App { + @Bean + public HttpHandler httpHandler(RouterFunction route, ServerFilter serverFilter, ViewResolver viewResolver) { + WebHandler webHandler = RouterFunctions.toWebHandler(route, HandlerStrategies.builder().viewResolver(viewResolver).build()); + return WebHttpHandlerBuilder.webHandler(webHandler).filter(serverFilter).build(); + } + public static void main(String[] args) { SpringApplication.run(App.class, args); } diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/DbHandler.java similarity index 74% rename from frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java rename to frameworks/Java/spring-webflux/src/main/java/benchmark/web/DbHandler.java index a7516af6636..bafddaf83c6 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/WebfluxHandler.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/DbHandler.java @@ -2,11 +2,9 @@ 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; @@ -21,26 +19,14 @@ import static java.util.Comparator.comparing; @Component -public class WebfluxHandler { +public class DbHandler { private final DbRepository dbRepository; - public WebfluxHandler(DbRepository dbRepository) { + public DbHandler(DbRepository dbRepository) { this.dbRepository = dbRepository; } - public Mono plaintext(ServerRequest request) { - return ServerResponse.ok() - .contentType(MediaType.TEXT_PLAIN) - .bodyValue("Hello, World!"); - } - - public Mono json(ServerRequest request) { - return ServerResponse.ok() - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(new Message("Hello, World!")); - } - public Mono db(ServerRequest request) { int id = randomWorldNumber(); Mono world = dbRepository.getWorld(id) @@ -52,7 +38,7 @@ public Mono db(ServerRequest request) { } public Mono queries(ServerRequest request) { - int queries = getQueries(request); + int queries = parseQueryCount(request.queryParams().getFirst("queries")); Mono> worlds = Flux.range(0, queries) .flatMap(i -> dbRepository.getWorld(randomWorldNumber())) @@ -64,13 +50,13 @@ public Mono queries(ServerRequest request) { }); } - private static int parseQueryCount(Optional maybeTextValue) { - if (!maybeTextValue.isPresent()) { + private static int parseQueryCount(String maybeTextValue) { + if (maybeTextValue == null) { return 1; } int parsedValue; try { - parsedValue = Integer.parseInt(maybeTextValue.get()); + parsedValue = Integer.parseInt(maybeTextValue); } catch (NumberFormatException e) { return 1; } @@ -78,7 +64,7 @@ private static int parseQueryCount(Optional maybeTextValue) { } public Mono updates(ServerRequest request) { - int queries = getQueries(request); + int queries = parseQueryCount(request.queryParams().getFirst("queries")); Mono> worlds = Flux.range(0, queries) .flatMap(i -> dbRepository.findAndUpdateWorld(randomWorldNumber(), randomWorldNumber())) @@ -101,10 +87,6 @@ public Mono fortunes(ServerRequest request) { .render("fortunes", Collections.singletonMap("fortunes", result)); } - private static int getQueries(ServerRequest request) { - return parseQueryCount(request.queryParam("queries")); - } - private static int randomWorldNumber() { return 1 + ThreadLocalRandom.current().nextInt(10000); } diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/JsonHandler.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/JsonHandler.java new file mode 100644 index 00000000000..6f4bc19249f --- /dev/null +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/JsonHandler.java @@ -0,0 +1,54 @@ +package benchmark.web; + +import java.util.Map; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; +import reactor.core.publisher.Mono; + +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.server.HandlerFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +@Component +public class JsonHandler implements HandlerFunction { + + private final ObjectWriter writer; + + public JsonHandler(ObjectMapper objectMapper) { + this.writer = objectMapper.writerFor(Map.class); + } + + @Override + public Mono handle(ServerRequest request) { + return ServerResponse.ok() + .body((message, context) -> { + DataBuffer buffer = serialize(request, Map.of("message", "Hello, world!")); + HttpHeaders headers = message.getHeaders(); + headers.setContentLength(buffer.readableByteCount()); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + return message.writeWith(Mono.just(buffer)); + }); + } + + private DataBuffer serialize(ServerRequest request, Object object) { + try { + byte[] bytes = this.writer.writeValueAsBytes(object); + return bufferFactory(request).wrap(bytes); + } + catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } + + private static DataBufferFactory bufferFactory(ServerRequest request) { + return request.exchange().getResponse().bufferFactory(); + } + +} \ 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/web/ServerFilter.java similarity index 83% rename from frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java rename to frameworks/Java/spring-webflux/src/main/java/benchmark/web/ServerFilter.java index 685ac39e6ad..38357eefdb2 100644 --- a/frameworks/Java/spring-webflux/src/main/java/benchmark/ServerFilter.java +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/ServerFilter.java @@ -1,6 +1,5 @@ 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; @@ -28,8 +27,8 @@ public void updateDate() { @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(), this.date); + headers.add(HttpHeaders.SERVER, SERVER_NAME); + headers.add(HttpHeaders.DATE, this.date); return chain.filter(exchange); } } \ No newline at end of file diff --git a/frameworks/Java/spring-webflux/src/main/java/benchmark/web/TextHandler.java b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/TextHandler.java new file mode 100644 index 00000000000..8abac92606d --- /dev/null +++ b/frameworks/Java/spring-webflux/src/main/java/benchmark/web/TextHandler.java @@ -0,0 +1,37 @@ +package benchmark.web; + +import java.nio.charset.StandardCharsets; + +import reactor.core.publisher.Mono; + +import org.springframework.core.io.buffer.DataBufferFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.server.HandlerFunction; +import org.springframework.web.reactive.function.server.ServerRequest; +import org.springframework.web.reactive.function.server.ServerResponse; + +@Component +public class TextHandler implements HandlerFunction { + + private static final byte[] TEXT_BODY = "Hello, World!".getBytes(StandardCharsets.UTF_8); + + private static final String TEXT_BODY_LENGTH = String.valueOf(TEXT_BODY.length); + + @Override + public Mono handle(ServerRequest request) { + return ServerResponse.ok() + .body((message, context) -> { + HttpHeaders headers = message.getHeaders(); + headers.add(HttpHeaders.CONTENT_LENGTH, TEXT_BODY_LENGTH); + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE); + return message.writeWith(Mono.just(bufferFactory(request).wrap(TEXT_BODY))); + }); + } + + private static DataBufferFactory bufferFactory(ServerRequest request) { + return request.exchange().getResponse().bufferFactory(); + } + +} \ 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 061797738c2..1499dc4f839 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 @@ -1,23 +1,32 @@ package benchmark.web; +import reactor.core.publisher.Mono; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.server.HandlerFunction; import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; @Configuration public class WebfluxRouter { @Bean - 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(); + public RouterFunction route( + TextHandler textHandler, JsonHandler jsonHandler, DbHandler dbHandler) { + + return request -> { + HandlerFunction fn = switch (request.uri().getRawPath()) { + case "/plaintext" -> textHandler; + case "/json" -> jsonHandler; + case "/db" -> dbHandler::db; + case "/queries" -> dbHandler::queries; + case "/updates" -> dbHandler::updates; + case "/fortunes" -> dbHandler::fortunes; + default -> r -> ServerResponse.notFound().build(); + }; + return Mono.just(fn); + }; } + } \ No newline at end of file diff --git a/frameworks/Java/spring/pom.xml b/frameworks/Java/spring/pom.xml index 9f131b9a23f..4a8d36e9749 100644 --- a/frameworks/Java/spring/pom.xml +++ b/frameworks/Java/spring/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 3.3.1 + 3.3.3 diff --git a/frameworks/Java/spring/spring.dockerfile b/frameworks/Java/spring/spring.dockerfile index 0598e9c1f28..f52c1f36df1 100644 --- a/frameworks/Java/spring/spring.dockerfile +++ b/frameworks/Java/spring/spring.dockerfile @@ -12,4 +12,4 @@ RUN java -Djarmode=tools -jar app.jar extract EXPOSE 8080 -CMD ["java", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app/app.jar", "--spring.profiles.active=jpa"] \ No newline at end of file +CMD ["java", "-XX:+DisableExplicitGC", "-XX:+UseStringDeduplication", "-Dlogging.level.root=OFF", "-jar", "app/app.jar", "--spring.profiles.active=jdbc"] \ 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 d0c13e06844..0484b46517e 100644 --- a/frameworks/Java/spring/src/main/java/hello/App.java +++ b/frameworks/Java/spring/src/main/java/hello/App.java @@ -4,8 +4,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.annotation.Bean; @@ -35,4 +33,5 @@ DataSource datasource(DataSourceProperties dataSourceProperties) { return dataSource; } + } diff --git a/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java b/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java index b59680aef5c..2bd4304a9ee 100644 --- a/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java +++ b/frameworks/Java/spring/src/main/java/hello/UpdateWorldServiceImpl.java @@ -3,7 +3,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import hello.controller.HelloController; +import hello.web.DbHandler; +import hello.web.WebmvcRouter; import hello.model.World; import hello.repository.DbRepository; @@ -33,7 +34,7 @@ public World updateWorld(int worldId) { int newRandomNumber; do { - newRandomNumber = HelloController.randomWorldNumber(); + newRandomNumber = DbHandler.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/web/DbHandler.java similarity index 50% rename from frameworks/Java/spring/src/main/java/hello/controller/HelloController.java rename to frameworks/Java/spring/src/main/java/hello/web/DbHandler.java index 5c11b82ac66..1611cf21170 100644 --- a/frameworks/Java/spring/src/main/java/hello/controller/HelloController.java +++ b/frameworks/Java/spring/src/main/java/hello/web/DbHandler.java @@ -1,79 +1,68 @@ -package hello.controller; +package hello.web; -import static java.util.Comparator.comparing; - -import java.util.List; 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; -import org.springframework.web.bind.annotation.ModelAttribute; -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; -@RestController -public final class HelloController { +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.function.RenderingResponse; +import org.springframework.web.servlet.function.ServerRequest; +import org.springframework.web.servlet.function.ServerResponse; + +import static java.util.Comparator.comparing; + +@Component +public class DbHandler { private DbRepository dbRepository; private UpdateWorldService updateWorldService; - public HelloController( - DbRepository dbRepository, - UpdateWorldService updateWorldService) { + public DbHandler(DbRepository dbRepository, UpdateWorldService updateWorldService) { this.dbRepository = dbRepository; this.updateWorldService = updateWorldService; } - @GetMapping("/plaintext") - String plaintext(HttpServletResponse response) { - response.setContentType(MediaType.TEXT_PLAIN_VALUE); - return "Hello, World!"; - } - - @GetMapping("/json") - Message json(HttpServletResponse response) { - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - return new Message("Hello, World!"); + ServerResponse db(ServerRequest request) { + return ServerResponse.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(dbRepository.getWorld(randomWorldNumber())); } - @GetMapping("/db") - World db(HttpServletResponse response) { - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - return dbRepository.getWorld(randomWorldNumber()); - } - - @GetMapping("/queries") - World[] queries(HttpServletResponse response, @RequestParam(required = false) String queries) { - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - return randomWorldNumbers().mapToObj(dbRepository::getWorld).limit(parseQueryCount(queries)) + ServerResponse queries(ServerRequest request) { + String queries = request.params().getFirst("queries"); + World[] worlds = randomWorldNumbers() + .mapToObj(dbRepository::getWorld).limit(parseQueryCount(queries)) .toArray(World[]::new); + return ServerResponse.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(worlds); } - @GetMapping("/updates") - World[] updates(HttpServletResponse response, @RequestParam(required = false) String queries) { - response.setContentType(MediaType.APPLICATION_JSON_VALUE); - return randomWorldNumbers() + ServerResponse updates(ServerRequest request) { + String queries = request.params().getFirst("queries"); + World[] worlds = randomWorldNumbers() .mapToObj(id -> updateWorldService.updateWorld(id)) .limit(parseQueryCount(queries)).toArray(World[]::new); + return ServerResponse.ok() + .contentType(MediaType.APPLICATION_JSON) + .body(worlds); } - @GetMapping("/fortunes") - @ModelAttribute("fortunes") - List fortunes(HttpServletResponse response) { - response.setContentType(MediaType.TEXT_HTML_VALUE); + ServerResponse fortunes(ServerRequest request) { var fortunes = dbRepository.fortunes(); - fortunes.add(new Fortune(0, "Additional fortune added at request time.")); fortunes.sort(comparing(fortune -> fortune.message)); - return fortunes; + return RenderingResponse + .create("fortunes") + .modelAttribute("fortunes", fortunes) + .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML_VALUE) + .build(); } private static final int MIN_WORLD_NUMBER = 1; diff --git a/frameworks/Java/spring/src/main/java/hello/web/JsonHandler.java b/frameworks/Java/spring/src/main/java/hello/web/JsonHandler.java new file mode 100644 index 00000000000..c6690811eca --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/web/JsonHandler.java @@ -0,0 +1,39 @@ +package hello.web; + +import java.util.Map; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.function.HandlerFunction; +import org.springframework.web.servlet.function.ServerRequest; +import org.springframework.web.servlet.function.ServerResponse; + +@Component +public class JsonHandler implements HandlerFunction { + + private final ObjectWriter writer; + + public JsonHandler(ObjectMapper objectMapper) { + this.writer = objectMapper.writerFor(Map.class); + } + + @Override + public ServerResponse handle(ServerRequest request) { + try { + byte[] body = this.writer.writeValueAsBytes(Map.of("message", "Hello, world!")); + return ServerResponse.ok() + .contentLength(body.length) + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .body(body); + } + catch (JsonProcessingException ex) { + throw new RuntimeException(ex); + } + } + +} diff --git a/frameworks/Java/spring/src/main/java/hello/web/TextHandler.java b/frameworks/Java/spring/src/main/java/hello/web/TextHandler.java new file mode 100644 index 00000000000..b70b3010268 --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/web/TextHandler.java @@ -0,0 +1,27 @@ +package hello.web; + +import java.nio.charset.StandardCharsets; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.function.HandlerFunction; +import org.springframework.web.servlet.function.ServerRequest; +import org.springframework.web.servlet.function.ServerResponse; + +@Component +public class TextHandler implements HandlerFunction { + + private static final byte[] TEXT_BODY = "Hello, World!".getBytes(StandardCharsets.UTF_8); + + private static final String TEXT_BODY_LENGTH = String.valueOf(TEXT_BODY.length); + + @Override + public ServerResponse handle(ServerRequest request) { + return ServerResponse.ok() + .header(HttpHeaders.CONTENT_LENGTH, TEXT_BODY_LENGTH) + .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE) + .body(TEXT_BODY); + } + +} diff --git a/frameworks/Java/spring/src/main/java/hello/web/WebmvcRouter.java b/frameworks/Java/spring/src/main/java/hello/web/WebmvcRouter.java new file mode 100644 index 00000000000..0a5810affd2 --- /dev/null +++ b/frameworks/Java/spring/src/main/java/hello/web/WebmvcRouter.java @@ -0,0 +1,32 @@ +package hello.web; + +import java.util.Optional; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.function.HandlerFunction; +import org.springframework.web.servlet.function.RouterFunction; +import org.springframework.web.servlet.function.ServerResponse; + +@Configuration +public class WebmvcRouter { + + @Bean + public RouterFunction route( + TextHandler textHandler, + JsonHandler jsonHandler, + DbHandler dbHandler) { + + return request -> Optional.of((HandlerFunction) r -> + switch (r.uri().getRawPath()) { + case "/plaintext" -> textHandler.handle(r); + case "/json" -> jsonHandler.handle(r); + case "/db" -> dbHandler.db(r); + case "/queries" -> dbHandler.queries(r); + case "/updates" -> dbHandler.updates(r); + case "/fortunes" -> dbHandler.fortunes(r); + default -> ServerResponse.notFound().build(); + }); + } +} + diff --git a/frameworks/Java/spring/src/main/resources/application.yml b/frameworks/Java/spring/src/main/resources/application.yml index 4796669a8e5..4f6592dc53b 100644 --- a/frameworks/Java/spring/src/main/resources/application.yml +++ b/frameworks/Java/spring/src/main/resources/application.yml @@ -1,12 +1,10 @@ --- spring: - 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 + 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.MongoDataAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration --- spring: @@ -31,7 +29,7 @@ spring: activate: on-profile: jpa autoconfigure: - exclude: org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration + exclude: org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect @@ -41,7 +39,7 @@ spring: 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 + exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration spring.data.mongodb: host: tfb-database @@ -55,3 +53,4 @@ spring: server.server-header: Spring server.servlet.encoding.force: true +spring.jpa.open-in-view: false From 8afa827e93500685666071353455ce281c4c69c2 Mon Sep 17 00:00:00 2001 From: Joan Miquel Date: Thu, 5 Sep 2024 18:30:18 +0200 Subject: [PATCH 28/40] [php] Fix Leaf v3.6 dockerfiles (#9250) * Leafphp fix dockerfiles * Clean event install --- frameworks/PHP/leaf/leaf-workerman.dockerfile | 15 ++++++++------- frameworks/PHP/leaf/leaf.dockerfile | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/frameworks/PHP/leaf/leaf-workerman.dockerfile b/frameworks/PHP/leaf/leaf-workerman.dockerfile index eaa11589d3a..ddcc5dc928c 100644 --- a/frameworks/PHP/leaf/leaf-workerman.dockerfile +++ b/frameworks/PHP/leaf/leaf-workerman.dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive @@ -7,21 +7,22 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get update -yqq > /dev/null && apt-get install -yqq git \ - php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl > /dev/null + php8.3-cli php8.3-mysql php8.3-mbstring php8.3-xml php8.3-curl php8.3-zip > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -RUN apt-get install -y php-pear php8.3-dev libevent-dev > /dev/null -RUN pecl install event-3.1.3 > /dev/null && echo "extension=event.so" > /etc/php/8.3/cli/conf.d/event.ini +RUN apt-get install -y libevent-dev php8.3-dev > /dev/null \ + && pecl install event-3.1.4 > /dev/null \ + && echo "extension=event.so" > /etc/php/8.3/cli/conf.d/event.ini -COPY deploy/conf/cli-php.ini /etc/php/8.3/cli/php.ini +COPY --link deploy/conf/cli-php.ini /etc/php/8.3/cli/php.ini -ADD ./ /leaf WORKDIR /leaf +COPY --link . . EXPOSE 8080 -RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet +RUN composer install --optimize-autoloader --classmap-authoritative --no-dev --quiet RUN composer require joanhey/adapterman:^0.6 --quiet diff --git a/frameworks/PHP/leaf/leaf.dockerfile b/frameworks/PHP/leaf/leaf.dockerfile index 167a5af7039..52a4c2f704c 100644 --- a/frameworks/PHP/leaf/leaf.dockerfile +++ b/frameworks/PHP/leaf/leaf.dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:24.04 ARG DEBIAN_FRONTEND=noninteractive @@ -7,14 +7,14 @@ RUN LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php > /dev/null && \ apt-get update -yqq > /dev/null && apt-get upgrade -yqq > /dev/null RUN apt-get install -yqq nginx git unzip \ - php8.3 php8.3-common php8.3-cli php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl > /dev/null + php8.3-cli php8.3-fpm php8.3-mysql php8.3-xml php8.3-curl php8.3-zip > /dev/null COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY deploy/conf/* /etc/php/8.3/fpm/ +COPY --link deploy/conf/* /etc/php/8.3/fpm/ -ADD ./ /leaf WORKDIR /leaf +COPY --link . . RUN if [ $(nproc) = 2 ]; then sed -i "s|pm.max_children = 1024|pm.max_children = 512|g" /etc/php/8.3/fpm/php-fpm.conf ; fi; From 91cefe6b137714379b5c5f182e3ef63a409418bb Mon Sep 17 00:00:00 2001 From: fakeshadow <24548779@qq.com> Date: Fri, 6 Sep 2024 04:03:14 +0800 Subject: [PATCH 29/40] [xitca-web] add connection pool (#9252) * [xitca-web] connection pool * fix plaintext. * update dep * simplify api --- frameworks/Rust/xitca-web/Cargo.lock | 43 ++++-- frameworks/Rust/xitca-web/Cargo.toml | 2 +- frameworks/Rust/xitca-web/rustfmt.toml | 1 + frameworks/Rust/xitca-web/src/db.rs | 169 ++++++++++++--------- frameworks/Rust/xitca-web/src/db_diesel.rs | 6 +- frameworks/Rust/xitca-web/src/main.rs | 55 +++---- frameworks/Rust/xitca-web/src/main_axum.rs | 24 +-- frameworks/Rust/xitca-web/src/main_iou.rs | 56 ++----- frameworks/Rust/xitca-web/src/main_sync.rs | 10 +- frameworks/Rust/xitca-web/src/ser.rs | 73 ++++++--- frameworks/Rust/xitca-web/src/util.rs | 4 +- 11 files changed, 234 insertions(+), 209 deletions(-) create mode 100644 frameworks/Rust/xitca-web/rustfmt.toml diff --git a/frameworks/Rust/xitca-web/Cargo.lock b/frameworks/Rust/xitca-web/Cargo.lock index 1f1f0e18a74..00bf2423449 100644 --- a/frameworks/Rust/xitca-web/Cargo.lock +++ b/frameworks/Rust/xitca-web/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", @@ -149,9 +149,9 @@ checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" dependencies = [ "shlex", ] @@ -218,9 +218,9 @@ dependencies = [ [[package]] name = "diesel" -version = "2.2.3" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e13bab2796f412722112327f3e575601a3e9cdcbe426f0d30dbf43f3f5dc71" +checksum = "158fe8e2e68695bd615d7e4f3227c0727b151330d3e253b525086c348d055d5e" dependencies = [ "bitflags 2.6.0", "byteorder", @@ -631,6 +631,24 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.5" @@ -869,9 +887,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -927,6 +945,12 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -1319,10 +1343,11 @@ dependencies = [ [[package]] name = "xitca-postgres" version = "0.1.0" -source = "git+https://github.com/HFQR/xitca-web.git?rev=6870448#687044829f0e89bab3efafcf7fb53e53167ad32c" +source = "git+https://github.com/HFQR/xitca-web.git?rev=9835c0b#9835c0b79ebd77f01b74e3ccb1c9893f022db9f3" dependencies = [ "fallible-iterator", "percent-encoding", + "phf", "postgres-protocol", "postgres-types", "tokio", diff --git a/frameworks/Rust/xitca-web/Cargo.toml b/frameworks/Rust/xitca-web/Cargo.toml index 84eb12264b3..1d6ccc17751 100644 --- a/frameworks/Rust/xitca-web/Cargo.toml +++ b/frameworks/Rust/xitca-web/Cargo.toml @@ -95,5 +95,5 @@ codegen-units = 1 panic = "abort" [patch.crates-io] -xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "6870448" } +xitca-postgres = { git = "https://github.com/HFQR/xitca-web.git", rev = "9835c0b" } mio = { git = "https://github.com/fakeshadow/mio", rev = "9bae6012b7ecfc6083350785f71a5e8265358178" } diff --git a/frameworks/Rust/xitca-web/rustfmt.toml b/frameworks/Rust/xitca-web/rustfmt.toml new file mode 100644 index 00000000000..866c7561055 --- /dev/null +++ b/frameworks/Rust/xitca-web/rustfmt.toml @@ -0,0 +1 @@ +max_width = 120 \ No newline at end of file diff --git a/frameworks/Rust/xitca-web/src/db.rs b/frameworks/Rust/xitca-web/src/db.rs index 276eb93ec9e..0b7a18601fb 100644 --- a/frameworks/Rust/xitca-web/src/db.rs +++ b/frameworks/Rust/xitca-web/src/db.rs @@ -1,9 +1,7 @@ use std::fmt::Write; use xitca_io::bytes::BytesMut; -use xitca_postgres::{ - pipeline::Pipeline, statement::Statement, AsyncLendingIterator, SharedClient, -}; +use xitca_postgres::{pipeline::Pipeline, AsyncLendingIterator, Pool, Type}; use super::{ ser::{Fortune, Fortunes, World}, @@ -11,64 +9,63 @@ use super::{ }; pub struct Client { - client: SharedClient, + pool: Pool, #[cfg(not(feature = "pg-sync"))] shared: std::cell::RefCell, #[cfg(feature = "pg-sync")] shared: std::sync::Mutex, - fortune: Statement, - world: Statement, - updates: Box<[Statement]>, + updates: Box<[Box]>, } type Shared = (Rand, BytesMut); -pub async fn create() -> HandleResult { - let mut client = SharedClient::new(DB_URL.to_string()).await?; +const FORTUNE_SQL: &str = "SELECT * FROM fortune"; - let fortune = client.prepare_cached("SELECT * FROM fortune", &[]).await?; +const FORTUNE_SQL_TYPES: &[Type] = &[]; - let world = client - .prepare_cached("SELECT * FROM world WHERE id=$1", &[]) - .await?; +const WORLD_SQL: &str = "SELECT * FROM world WHERE id=$1"; - let mut updates = Vec::new(); +const WORLD_SQL_TYPES: &[Type] = &[Type::INT4]; - // a dummy statement as placeholder of 0 index. - // avoid off by one calculation when using non zero u16 as slicing index. - updates.push(Statement::default()); +fn update_query(num: usize) -> Box { + const PREFIX: &str = "UPDATE world SET randomNumber = w.r FROM (VALUES "; + const SUFFIX: &str = ") AS w (i,r) WHERE world.id = w.i"; - for num in 1..=500u16 { - let mut pl = 1; - let mut q = String::new(); - q.push_str("UPDATE world SET randomnumber = CASE id "); - for _ in 1..=num { - let _ = write!(&mut q, "when ${} then ${} ", pl, pl + 1); - pl += 2; - } - q.push_str("ELSE randomnumber END WHERE id IN ("); - for _ in 1..=num { - let _ = write!(&mut q, "${},", pl); - pl += 1; - } - q.pop(); - q.push(')'); + let (_, mut query) = (1..=num).fold((1, String::from(PREFIX)), |(idx, mut query), _| { + write!(query, "(${}::int,${}::int),", idx, idx + 1).unwrap(); + (idx + 2, query) + }); - let st = client.prepare_cached(&q, &[]).await?; - updates.push(st); - } + query.pop(); + + query.push_str(SUFFIX); + + query.into_boxed_str() +} + +pub async fn create() -> HandleResult { + let pool = Pool::builder(DB_URL).capacity(1).build()?; let shared = (Rand::default(), BytesMut::new()); + let updates = core::iter::once(Box::from("")) + .chain((1..=500).map(update_query)) + .collect::]>>(); + + { + let mut conn = pool.get().await?; + for update in updates.iter().skip(1) { + conn.prepare(update, &[]).await?; + } + } + Ok(Client { - client, + pool, #[cfg(not(feature = "pg-sync"))] shared: std::cell::RefCell::new(shared), #[cfg(feature = "pg-sync")] shared: std::sync::Mutex::new(shared), - fortune, - world, - updates: updates.into_boxed_slice(), + updates, }) } @@ -84,29 +81,26 @@ impl Client { } pub async fn get_world(&self) -> HandleResult { + let mut conn = self.pool.get().await?; + let stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; let id = self.shared().0.gen_id(); - self.client - .query_raw(&self.world, [id]) - .await? - .try_next() - .await? - .map(|row| World::new(row.get_raw(0), row.get_raw(1))) - .ok_or_else(|| "World does not exist".into()) + let mut res = conn.consume().query_raw(&stmt, [id])?; + let row = res.try_next().await?.ok_or_else(|| "World does not exist")?; + Ok(World::new(row.get_raw(0), row.get_raw(1))) } pub async fn get_worlds(&self, num: u16) -> HandleResult> { let len = num as usize; + let mut conn = self.pool.get().await?; + let stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; + let mut res = { let (ref mut rng, ref mut buf) = *self.shared(); - let mut pipe = Pipeline::with_capacity_from_buf(len, buf); - - (0..num).try_for_each(|_| pipe.query_raw(&self.world, [rng.gen_id()]))?; - - self.client.pipeline(pipe) - } - .await?; + (0..num).try_for_each(|_| pipe.query_raw(&stmt, [rng.gen_id()]))?; + conn.consume().pipeline(pipe)? + }; let mut worlds = Vec::with_capacity(len); @@ -122,37 +116,34 @@ impl Client { pub async fn update(&self, num: u16) -> HandleResult> { let len = num as usize; - let mut params = Vec::new(); - params.reserve(len * 3); + let update = self.updates.get(len).ok_or_else(|| "num out of bound")?; + + let mut conn = self.pool.get().await?; + let world_stmt = conn.prepare(WORLD_SQL, WORLD_SQL_TYPES).await?; + let update_stmt = conn.prepare(&update, &[]).await?; + + let mut params = Vec::with_capacity(len); let mut res = { let (ref mut rng, ref mut buf) = *self.shared(); - let mut pipe = Pipeline::with_capacity_from_buf(len + 1, buf); - (0..num).try_for_each(|_| { let w_id = rng.gen_id(); let r_id = rng.gen_id(); - params.extend([w_id, r_id]); - pipe.query_raw(&self.world, [w_id]) + params.push([w_id, r_id]); + pipe.query_raw(&world_stmt, [w_id]) })?; + pipe.query_raw(&update_stmt, sort_update_params(¶ms))?; + conn.consume().pipeline(pipe)? + }; - params.extend_from_within(..len); - - let st = self.updates.get(len).unwrap(); - pipe.query_raw(st, ¶ms)?; - - self.client.pipeline(pipe) - } - .await?; + let mut worlds = Vec::with_capacity(len); - let mut worlds = Vec::new(); - worlds.reserve(len); - let mut r_ids = params.into_iter().skip(1).step_by(2); + let mut r_ids = params.into_iter(); while let Some(mut item) = res.try_next().await? { while let Some(row) = item.try_next().await? { - let r_id = r_ids.next().unwrap(); + let r_id = r_ids.next().unwrap()[1]; worlds.push(World::new(row.get_raw(0), r_id)) } } @@ -164,12 +155,46 @@ impl Client { let mut items = Vec::with_capacity(32); items.push(Fortune::new(0, "Additional fortune added at request time.")); - let mut res = self.client.query_raw::<[i32; 0]>(&self.fortune, []).await?; + let mut conn = self.pool.get().await?; + let stmt = conn.prepare(FORTUNE_SQL, FORTUNE_SQL_TYPES).await?; + let mut res = conn.consume().query_raw::<[i32; 0]>(&stmt, [])?; + while let Some(row) = res.try_next().await? { items.push(Fortune::new(row.get_raw(0), row.get_raw::(1))); } + items.sort_by(|it, next| it.message.cmp(&next.message)); Ok(Fortunes::new(items)) } } + +fn sort_update_params(params: &Vec<[i32; 2]>) -> impl ExactSizeIterator { + let mut params = params.clone(); + params.sort_by(|a, b| a[0].cmp(&b[0])); + + struct ParamIter(I); + + impl Iterator for ParamIter + where + I: Iterator, + { + type Item = I::Item; + + #[inline] + fn next(&mut self) -> Option { + self.0.next() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } + } + + // impl depends on compiler optimization to flat Vec<[T]> to Vec when inferring + // it's size hint. possible to cause runtime panic. + impl ExactSizeIterator for ParamIter where I: Iterator {} + + ParamIter(params.into_iter().flatten()) +} diff --git a/frameworks/Rust/xitca-web/src/db_diesel.rs b/frameworks/Rust/xitca-web/src/db_diesel.rs index 79ba4c9a69a..2cd44344499 100644 --- a/frameworks/Rust/xitca-web/src/db_diesel.rs +++ b/frameworks/Rust/xitca-web/src/db_diesel.rs @@ -43,11 +43,7 @@ impl _Pool { let w_id = self.rng.lock().unwrap().gen_id(); let mut conn = self.pool.get()?; - world - .filter(id.eq(w_id)) - .load(&mut conn)? - .pop() - .ok_or_else(not_found) + world.filter(id.eq(w_id)).load(&mut conn)?.pop().ok_or_else(not_found) } pub fn get_worlds(&self, num: u16) -> HandleResult> { diff --git a/frameworks/Rust/xitca-web/src/main.rs b/frameworks/Rust/xitca-web/src/main.rs index 8405c986717..06c925bbb25 100755 --- a/frameworks/Rust/xitca-web/src/main.rs +++ b/frameworks/Rust/xitca-web/src/main.rs @@ -3,26 +3,20 @@ mod ser; mod util; use xitca_http::{ - body::Once, - bytes::Bytes, h1::RequestBody, - http::{ - self, - const_header_value::{TEXT, TEXT_HTML_UTF8}, - header::{CONTENT_TYPE, SERVER}, - IntoResponse, RequestExt, + http::{header::SERVER, StatusCode}, + util::service::{ + route::get, + router::{Router, RouterError}, }, - util::service::{route::get, router::Router}, HttpServiceBuilder, }; use xitca_service::{fn_service, Service, ServiceExt}; -use ser::{json_response, Message}; +use ser::{error_response, IntoResponse, Message, Request, Response}; use util::{context_mw, HandleResult, QueryParse, SERVER_HEADER_VALUE}; -type Request = http::Request>; -type Response = http::Response>; -type Ctx<'a> = util::Ctx<'a, Request>; +type Ctx<'a> = util::Ctx<'a, Request>; fn main() -> std::io::Result<()> { let service = Router::new() @@ -32,7 +26,7 @@ fn main() -> std::io::Result<()> { .insert("/fortunes", get(fn_service(fortunes))) .insert("/queries", get(fn_service(queries))) .insert("/updates", get(fn_service(updates))) - .enclosed_fn(middleware_fn) + .enclosed_fn(middleware) .enclosed(context_mw()) .enclosed(HttpServiceBuilder::h1().io_uring()); xitca_server::Builder::new() @@ -41,53 +35,54 @@ fn main() -> std::io::Result<()> { .wait() } -async fn middleware_fn(service: &S, req: Ctx<'_>) -> Result +async fn middleware(service: &S, req: Ctx<'_>) -> Result where - S: for<'c> Service, Response = Response, Error = E>, + S: for<'c> Service, Response = Response, Error = RouterError>, { - service.call(req).await.map(|mut res| { - res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE); - res - }) + let mut res = service.call(req).await.unwrap_or_else(|e| match e { + RouterError::Match(_) => error_response(StatusCode::NOT_FOUND), + RouterError::NotAllowed(_) => error_response(StatusCode::METHOD_NOT_ALLOWED), + RouterError::Service(e) => { + println!("{e}"); + error_response(StatusCode::INTERNAL_SERVER_ERROR) + } + }); + res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE); + Ok(res) } async fn plain_text(ctx: Ctx<'_>) -> HandleResult { - let (req, _) = ctx.into_parts(); - let mut res = req.into_response(const { Bytes::from_static(b"Hello, World!") }); - res.headers_mut().insert(CONTENT_TYPE, TEXT); - Ok(res) + ctx.into_parts().0.text_response() } async fn json(ctx: Ctx<'_>) -> HandleResult { let (req, state) = ctx.into_parts(); - json_response(req, &mut state.write_buf.borrow_mut(), &Message::new()) + req.json_response(state, &Message::new()) } async fn db(ctx: Ctx<'_>) -> HandleResult { let (req, state) = ctx.into_parts(); let world = state.client.get_world().await?; - json_response(req, &mut state.write_buf.borrow_mut(), &world) + req.json_response(state, &world) } async fn fortunes(ctx: Ctx<'_>) -> HandleResult { let (req, state) = ctx.into_parts(); use sailfish::TemplateOnce; let fortunes = state.client.tell_fortune().await?.render_once()?; - let mut res = req.into_response(Bytes::from(fortunes)); - res.headers_mut().insert(CONTENT_TYPE, TEXT_HTML_UTF8); - Ok(res) + req.html_response(fortunes) } async fn queries(ctx: Ctx<'_>) -> HandleResult { let (req, state) = ctx.into_parts(); let num = req.uri().query().parse_query(); let worlds = state.client.get_worlds(num).await?; - json_response(req, &mut state.write_buf.borrow_mut(), worlds.as_slice()) + req.json_response(state, &worlds) } async fn updates(ctx: Ctx<'_>) -> HandleResult { let (req, state) = ctx.into_parts(); let num = req.uri().query().parse_query(); let worlds = state.client.update(num).await?; - json_response(req, &mut state.write_buf.borrow_mut(), worlds.as_slice()) + req.json_response(state, &worlds) } diff --git a/frameworks/Rust/xitca-web/src/main_axum.rs b/frameworks/Rust/xitca-web/src/main_axum.rs index d15aaefdc6e..02fdfba8a20 100644 --- a/frameworks/Rust/xitca-web/src/main_axum.rs +++ b/frameworks/Rust/xitca-web/src/main_axum.rs @@ -99,9 +99,7 @@ mod tower_compat { HttpServiceBuilder, }; use xitca_io::net::io_uring::TcpStream; - use xitca_service::{ - fn_build, middleware::UncheckedReady, ready::ReadyService, Service, ServiceExt, - }; + use xitca_service::{fn_build, middleware::UncheckedReady, ready::ReadyService, Service, ServiceExt}; use xitca_web::service::tower_http_compat::{CompatReqBody, CompatResBody}; pub struct TowerHttp { @@ -112,17 +110,11 @@ mod tower_compat { impl TowerHttp { pub fn service( func: F, - ) -> impl Service< - Response = impl ReadyService + Service<(TcpStream, SocketAddr)>, - Error = impl fmt::Debug, - > + ) -> impl Service, Error = impl fmt::Debug> where F: Fn() -> Fut + Send + Sync + Clone, Fut: Future>, - S: tower::Service< - Request, ()>>, - Response = Response, - >, + S: tower::Service, ()>>, Response = Response>, S::Error: fmt::Debug, B: Body + Send + 'static, { @@ -142,18 +134,12 @@ mod tower_compat { impl Service>> for TowerHttp where - S: tower::Service< - Request, ()>>, - Response = Response, - >, + S: tower::Service, ()>>, Response = Response>, { type Response = Response>; type Error = S::Error; - async fn call( - &self, - req: Request>, - ) -> Result { + async fn call(&self, req: Request>) -> Result { let (parts, ext) = req.into_parts(); let req = Request::from_parts(parts, CompatReqBody::new(ext, ())); let fut = self.service.borrow_mut().call(req); diff --git a/frameworks/Rust/xitca-web/src/main_iou.rs b/frameworks/Rust/xitca-web/src/main_iou.rs index 8ca722f1fbe..af6f8424db0 100644 --- a/frameworks/Rust/xitca-web/src/main_iou.rs +++ b/frameworks/Rust/xitca-web/src/main_iou.rs @@ -12,31 +12,22 @@ use std::{convert::Infallible, fmt, future::poll_fn, io, pin::pin}; use futures_core::stream::Stream; use xitca_http::{ - body::Once, date::DateTimeService, h1::proto::context::Context, - http::{ - self, - const_header_value::{TEXT, TEXT_HTML_UTF8}, - header::{CONTENT_TYPE, SERVER}, - IntoResponse, RequestExt, StatusCode, - }, + http::{header::SERVER, StatusCode}, }; use xitca_io::{ - bytes::{Bytes, BytesMut}, + bytes::BytesMut, io_uring::BoundedBuf, net::{io_uring::TcpStream as IOUTcpStream, TcpStream}, }; use xitca_service::{fn_build, fn_service, middleware::UncheckedReady, Service, ServiceExt}; use self::{ - ser::{json_response, Message}, + ser::{error_response, IntoResponse, Message, Request, Response}, util::{context_mw, Ctx, QueryParse, SERVER_HEADER_VALUE}, }; -type Request = http::Request>; -type Response = http::Response>; - fn main() -> io::Result<()> { let service = fn_service(handler) .enclosed(context_mw()) @@ -53,47 +44,31 @@ fn main() -> io::Result<()> { .wait() } -async fn handler(ctx: Ctx<'_, Request>) -> Result { +async fn handler(ctx: Ctx<'_, Request<()>>) -> Result { let (req, state) = ctx.into_parts(); let mut res = match req.uri().path() { - "/plaintext" => { - let mut res = req.into_response(const { Bytes::from_static(b"Hello, World!") }); - res.headers_mut().insert(CONTENT_TYPE, TEXT); - res - } - "/json" => json_response(req, &mut state.write_buf.borrow_mut(), &Message::new()).unwrap(), + "/plaintext" => req.text_response().unwrap(), + "/json" => req.json_response(state, &Message::new()).unwrap(), "/db" => { let world = state.client.get_world().await.unwrap(); - json_response(req, &mut state.write_buf.borrow_mut(), &world).unwrap() + req.json_response(state, &world).unwrap() } "/queries" => { let num = req.uri().query().parse_query(); let worlds = state.client.get_worlds(num).await.unwrap(); - json_response(req, &mut state.write_buf.borrow_mut(), worlds.as_slice()).unwrap() + req.json_response(state, &worlds).unwrap() } "/updates" => { let num = req.uri().query().parse_query(); let worlds = state.client.update(num).await.unwrap(); - json_response(req, &mut state.write_buf.borrow_mut(), worlds.as_slice()).unwrap() + req.json_response(state, &worlds).unwrap() } "/fortunes" => { use sailfish::TemplateOnce; - let fortunes = state - .client - .tell_fortune() - .await - .unwrap() - .render_once() - .unwrap(); - let mut res = req.into_response(Bytes::from(fortunes)); - res.headers_mut().append(CONTENT_TYPE, TEXT_HTML_UTF8); - res - } - _ => { - let mut res = req.into_response(Bytes::new()); - *res.status_mut() = StatusCode::NOT_FOUND; - res + let fortunes = state.client.tell_fortune().await.unwrap().render_once().unwrap(); + req.html_response(fortunes).unwrap() } + _ => error_response(StatusCode::NOT_FOUND), }; res.headers_mut().insert(SERVER, SERVER_HEADER_VALUE); Ok(res) @@ -107,7 +82,7 @@ struct Http1IOU { // runner for http service. impl Service for Http1IOU where - S: Service, + S: Service, Response = Response>, S::Error: fmt::Debug, { type Response = (); @@ -138,10 +113,7 @@ where let (parts, body) = self.service.call(req).await.unwrap().into_parts(); let mut encoder = ctx.encode_head(parts, &body, &mut write_buf).unwrap(); let mut body = pin!(body); - let chunk = poll_fn(|cx| body.as_mut().poll_next(cx)) - .await - .unwrap() - .unwrap(); + let chunk = poll_fn(|cx| body.as_mut().poll_next(cx)).await.unwrap().unwrap(); encoder.encode(chunk, &mut write_buf); encoder.encode_eof(&mut write_buf); } diff --git a/frameworks/Rust/xitca-web/src/main_sync.rs b/frameworks/Rust/xitca-web/src/main_sync.rs index cf36166ac70..ae49ebf5827 100644 --- a/frameworks/Rust/xitca-web/src/main_sync.rs +++ b/frameworks/Rust/xitca-web/src/main_sync.rs @@ -51,17 +51,11 @@ fn fortunes(StateOwn(pool): StateOwn) -> HandleResult> { } #[route("/queries", method = get)] -fn queries( - Query(Num(num)): Query, - StateOwn(pool): StateOwn, -) -> HandleResult> { +fn queries(Query(Num(num)): Query, StateOwn(pool): StateOwn) -> HandleResult> { pool.get_worlds(num).map(Json) } #[route("/updates", method = get)] -fn updates( - Query(Num(num)): Query, - StateOwn(pool): StateOwn, -) -> HandleResult> { +fn updates(Query(Num(num)): Query, StateOwn(pool): StateOwn) -> HandleResult> { pool.update(num).map(Json) } diff --git a/frameworks/Rust/xitca-web/src/ser.rs b/frameworks/Rust/xitca-web/src/ser.rs index ca1c56caf70..e52f2f9c92c 100644 --- a/frameworks/Rust/xitca-web/src/ser.rs +++ b/frameworks/Rust/xitca-web/src/ser.rs @@ -5,11 +5,19 @@ use std::borrow::Cow; use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize, Serializer}; use xitca_http::{ body::Once, - bytes::{BufMutWriter, Bytes, BytesMut}, - http::{const_header_value::JSON, header::CONTENT_TYPE, IntoResponse, Request, Response}, + bytes::{BufMutWriter, Bytes}, + http::{ + self, + const_header_value::{JSON, TEXT, TEXT_HTML_UTF8}, + header::CONTENT_TYPE, + IntoResponse as _, RequestExt, StatusCode, + }, }; -use crate::util::Error; +use crate::util::{Error, State}; + +const HELLO: &str = "Hello, World!"; +const HELLO_BYTES: &[u8] = HELLO.as_bytes(); #[derive(Clone)] pub struct Message { @@ -19,9 +27,7 @@ pub struct Message { impl Message { #[inline] pub const fn new() -> Self { - Self { - message: "Hello, World!", - } + Self { message: HELLO } } } @@ -128,8 +134,7 @@ impl<'de> Deserialize<'de> for Num { where V: MapAccess<'de>, { - map.next_key::()? - .ok_or_else(|| Error::missing_field("q"))?; + map.next_key::()?.ok_or_else(|| Error::missing_field("q"))?; let q = map.next_value::().unwrap_or(1); let q = cmp::min(500, cmp::max(1, q)); Ok(Num(q)) @@ -163,16 +168,44 @@ impl Serialize for World { } } -pub fn json_response( - req: Request, - buf: &mut BytesMut, - value: &S, -) -> Result>, Error> -where - S: ?Sized + Serialize, -{ - serde_json::to_writer(BufMutWriter(buf), value)?; - let mut res = req.into_response(buf.split().freeze()); - res.headers_mut().insert(CONTENT_TYPE, JSON); - Ok(res) +pub type Request = http::Request>; +pub type Response = http::Response>; + +pub trait IntoResponse: Sized { + fn json_response(self, state: &State, val: &impl Serialize) -> Result; + + fn text_response(self) -> Result; + + fn html_response(self, val: String) -> Result; +} + +impl IntoResponse for Request { + fn json_response(self, state: &State, val: &impl Serialize) -> Result { + let buf = &mut *state.write_buf.borrow_mut(); + serde_json::to_writer(BufMutWriter(buf), val)?; + let mut res = self.into_response(buf.split().freeze()); + res.headers_mut().insert(CONTENT_TYPE, JSON); + Ok(res) + } + + fn text_response(self) -> Result { + let mut res = self.into_response(const { Bytes::from_static(HELLO_BYTES) }); + res.headers_mut().insert(CONTENT_TYPE, TEXT); + Ok(res) + } + + fn html_response(self, val: String) -> Result { + let mut res = self.into_response(Bytes::from(val)); + res.headers_mut().insert(CONTENT_TYPE, TEXT_HTML_UTF8); + Ok(res) + } +} + +#[cold] +#[inline(never)] +pub fn error_response(status: StatusCode) -> Response { + http::Response::builder() + .status(status) + .body(Once::new(Bytes::new())) + .unwrap() } diff --git a/frameworks/Rust/xitca-web/src/util.rs b/frameworks/Rust/xitca-web/src/util.rs index dc0476a5d15..707279559ba 100755 --- a/frameworks/Rust/xitca-web/src/util.rs +++ b/frameworks/Rust/xitca-web/src/util.rs @@ -65,9 +65,7 @@ mod non_wasm { pub type Ctx<'a, Req> = Context<'a, Req, State>; - pub fn context_mw( - ) -> ContextBuilder Pin>>>>> - { + pub fn context_mw() -> ContextBuilder Pin>>>>> { ContextBuilder::new(|| { Box::pin(async { db::create().await.map(|client| State { From ced92062ee65608268915a8735de7ec427bcea54 Mon Sep 17 00:00:00 2001 From: Giovanni Barillari Date: Thu, 5 Sep 2024 22:03:30 +0200 Subject: [PATCH 30/40] [Python] Bump Granian to 1.6 (#9253) --- frameworks/Python/granian/requirements.txt | 2 +- frameworks/Python/granian/run.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/frameworks/Python/granian/requirements.txt b/frameworks/Python/granian/requirements.txt index 1a22a3ddfc2..90c02f2c8d4 100644 --- a/frameworks/Python/granian/requirements.txt +++ b/frameworks/Python/granian/requirements.txt @@ -1,4 +1,4 @@ asyncpg==0.29.0 -granian>=1.5.1,<1.6.0 +granian>=1.6.0,<1.7.0 jinja2==3.1.4 orjson==3.10.2 diff --git a/frameworks/Python/granian/run.py b/frameworks/Python/granian/run.py index 910b248422b..ef0724fad2f 100644 --- a/frameworks/Python/granian/run.py +++ b/frameworks/Python/granian/run.py @@ -7,9 +7,11 @@ if __name__ == '__main__': interface = sys.argv[1] threading_mode = sys.argv[2] + workers = multiprocessing.cpu_count() - #: split cores between the two loops - workers = round(multiprocessing.cpu_count() / 2) + if interface == "rsgi": + #: split cores between the two loops + workers = round(workers / 2) blocking_threads = None if interface == "wsgi": From 49663874d8b9bd42143fd20987a75dc90f8ed7f9 Mon Sep 17 00:00:00 2001 From: lospejos Date: Tue, 10 Sep 2024 23:10:44 +0300 Subject: [PATCH 31/40] Bumped version for Java, Jooby, Maven and other libraries/dependencies (#9182) * Bumped version for Java, Jooby, Maven and other libraries/dependencies * Bumped dependencies versions * Bumped dependencies versions * Bumped dependencies versions * Bumped dependencies versions * Fixed Resource_ issue * Bumped versions for Golang, Fiber and other dependencies * Bumped many deps versions, removed deprecated reuseBuffer() in Rocker * Bumped versions for Golang, Fiber and other dependencies --- frameworks/Go/fiber/fiber-prefork.dockerfile | 2 +- frameworks/Go/fiber/fiber.dockerfile | 2 +- frameworks/Go/fiber/src/go.mod | 30 ++++---- frameworks/Go/fiber/src/go.sum | 74 ++++++++----------- frameworks/Java/jooby/pom.xml | 12 +-- .../src/main/java/com/techempower/MvcApp.java | 2 +- frameworks/Kotlin/kooby/kooby.dockerfile | 2 +- frameworks/Kotlin/kooby/pom.xml | 20 ++--- .../Kotlin/kooby/src/main/kotlin/kooby/App.kt | 2 +- 9 files changed, 67 insertions(+), 79 deletions(-) diff --git a/frameworks/Go/fiber/fiber-prefork.dockerfile b/frameworks/Go/fiber/fiber-prefork.dockerfile index 85acc26ef6b..c741baca1b8 100644 --- a/frameworks/Go/fiber/fiber-prefork.dockerfile +++ b/frameworks/Go/fiber/fiber-prefork.dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.20 +FROM docker.io/golang:1.23 WORKDIR /fiber diff --git a/frameworks/Go/fiber/fiber.dockerfile b/frameworks/Go/fiber/fiber.dockerfile index 37f02a59405..23c8ab72ea7 100644 --- a/frameworks/Go/fiber/fiber.dockerfile +++ b/frameworks/Go/fiber/fiber.dockerfile @@ -1,4 +1,4 @@ -FROM docker.io/golang:1.20 +FROM docker.io/golang:1.23 WORKDIR /fiber diff --git a/frameworks/Go/fiber/src/go.mod b/frameworks/Go/fiber/src/go.mod index bb9b8bc5701..252db9355e6 100644 --- a/frameworks/Go/fiber/src/go.mod +++ b/frameworks/Go/fiber/src/go.mod @@ -1,30 +1,30 @@ module fiber/app -go 1.19 +go 1.23 require ( - github.com/goccy/go-json v0.10.0 + github.com/goccy/go-json v0.10.3 github.com/gofiber/fiber/v2 v2.52.5 - github.com/jackc/pgx/v5 v5.5.4 - github.com/valyala/quicktemplate v1.7.0 + github.com/jackc/pgx/v5 v5.6.0 + github.com/valyala/quicktemplate v1.8.0 ) require ( - github.com/andybalholm/brotli v1.0.5 // indirect - github.com/google/uuid v1.5.0 // indirect + github.com/andybalholm/brotli v1.1.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect - github.com/klauspost/compress v1.17.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/rivo/uniseg v0.4.7 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.51.0 // indirect + github.com/valyala/fasthttp v1.55.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/text v0.14.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect ) diff --git a/frameworks/Go/fiber/src/go.sum b/frameworks/Go/fiber/src/go.sum index 1414375d002..1cada1ee655 100644 --- a/frameworks/Go/fiber/src/go.sum +++ b/frameworks/Go/fiber/src/go.sum @@ -1,72 +1,60 @@ -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.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= -github.com/andybalholm/brotli v1.0.5/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/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/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= 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= +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/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/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/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/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.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= -github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 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-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 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.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= -github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= -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/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.8.0 h1:zU0tjbIqTRgKQzFY1L42zq0qR3eh4WoQQdIdqCysW5k= +github.com/valyala/quicktemplate v1.8.0/go.mod h1:qIqW8/igXt8fdrUln5kOSb+KWMaJ4Y8QUsfd1k6L2jM= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -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-20201119102817-f84b799fce68/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/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/frameworks/Java/jooby/pom.xml b/frameworks/Java/jooby/pom.xml index bd6ce1a1c68..99170fb8cfe 100644 --- a/frameworks/Java/jooby/pom.xml +++ b/frameworks/Java/jooby/pom.xml @@ -11,10 +11,10 @@ jooby - 3.2.4 - 4.1.111.Final + 3.2.9 + 4.1.112.Final 2.0.2 - 42.7.3 + 42.7.4 UTF-8 21 21 @@ -72,7 +72,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.5.0 + 3.6.0 add-source @@ -110,7 +110,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.12.1 + 3.13.0 @@ -130,7 +130,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.2 + 3.6.0 uber-jar diff --git a/frameworks/Java/jooby/src/main/java/com/techempower/MvcApp.java b/frameworks/Java/jooby/src/main/java/com/techempower/MvcApp.java index 68d09e0a472..ad40629a635 100644 --- a/frameworks/Java/jooby/src/main/java/com/techempower/MvcApp.java +++ b/frameworks/Java/jooby/src/main/java/com/techempower/MvcApp.java @@ -17,7 +17,7 @@ public static void main(String[] args) { /** Template engine: */ app.install(new RockerModule()); - app.mvc(new Resource(app.require(DataSource.class))); + app.mvc(new Resource_(app.require(DataSource.class))); }); } } diff --git a/frameworks/Kotlin/kooby/kooby.dockerfile b/frameworks/Kotlin/kooby/kooby.dockerfile index 56c278c467a..678fc57b8d4 100644 --- a/frameworks/Kotlin/kooby/kooby.dockerfile +++ b/frameworks/Kotlin/kooby/kooby.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.9.0-eclipse-temurin-17 +FROM maven:3.9.9-eclipse-temurin-22-alpine WORKDIR /kooby COPY pom.xml pom.xml COPY src src diff --git a/frameworks/Kotlin/kooby/pom.xml b/frameworks/Kotlin/kooby/pom.xml index 9ae92257022..4ff8df958da 100644 --- a/frameworks/Kotlin/kooby/pom.xml +++ b/frameworks/Kotlin/kooby/pom.xml @@ -12,12 +12,12 @@ kooby: jooby+kotlin - 3.0.5 - 42.7.2 + 3.3.0 + 42.7.4 UTF-8 - 17 - 17 - 1.8.21 + 22 + 22 + 2.0.20 kooby.AppKt @@ -52,7 +52,7 @@ com.mysql mysql-connector-j - 8.2.0 + 9.0.0 @@ -77,7 +77,7 @@ com.fizzed rocker-maven-plugin - 1.3.0 + 1.4.0 generate-rocker-templates @@ -98,7 +98,7 @@ kotlin-maven-plugin ${kotlin.version} - 17 + 22 @@ -127,7 +127,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.13.0 @@ -159,7 +159,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.2.4 + 3.6.0 uber-jar diff --git a/frameworks/Kotlin/kooby/src/main/kotlin/kooby/App.kt b/frameworks/Kotlin/kooby/src/main/kotlin/kooby/App.kt index edc43137b1b..958991e29d3 100644 --- a/frameworks/Kotlin/kooby/src/main/kotlin/kooby/App.kt +++ b/frameworks/Kotlin/kooby/src/main/kotlin/kooby/App.kt @@ -33,7 +33,7 @@ fun main(args: Array) { runApp(args, EVENT_LOOP) { /** Template engine: */ - install(RockerModule().reuseBuffer(true)) + install(RockerModule()) /** JSON: */ install(JacksonModule()) From ba6923509494dc5ed1d1b48d2f5e8f79c9bc0510 Mon Sep 17 00:00:00 2001 From: Dragos Varovici Date: Tue, 10 Sep 2024 14:11:29 -0600 Subject: [PATCH 32/40] Zap upgraded to 0.8 (#9254) * Zap upgraded to 0.8 * Zap 0.8 fixes --- frameworks/Zig/zap/build.zig | 42 +++++++-------- frameworks/Zig/zap/build.zig.zon | 34 +++++------- frameworks/Zig/zap/run.sh | 2 +- frameworks/Zig/zap/src/endpoints.zig | 33 ++++++------ frameworks/Zig/zap/src/main.zig | 11 ++-- frameworks/Zig/zap/src/middleware.zig | 10 ++-- frameworks/Zig/zap/src/pool.zig | 77 +++++++++++++++------------ frameworks/Zig/zap/zap.dockerfile | 46 ++++++++-------- 8 files changed, 128 insertions(+), 127 deletions(-) diff --git a/frameworks/Zig/zap/build.zig b/frameworks/Zig/zap/build.zig index 70c740351a1..762284c2acb 100644 --- a/frameworks/Zig/zap/build.zig +++ b/frameworks/Zig/zap/build.zig @@ -1,9 +1,12 @@ const std = @import("std"); +const ModuleMap = std.StringArrayHashMap(*std.Build.Module); +var gpa = std.heap.GeneralPurposeAllocator(.{}){}; +const allocator = gpa.allocator(); // Although this function looks imperative, note that its job is to // declaratively construct a build graph that will be executed by an external // runner. -pub fn build(b: *std.Build) void { +pub fn build(b: *std.Build) !void { // Standard target options allows the person running `zig build` to choose // what target to build for. Here we do not override the defaults, which // means any target is allowed, and the default is native. Other options @@ -15,41 +18,38 @@ pub fn build(b: *std.Build) void { // set a preferred release mode, allowing the user to decide how to optimize. const optimize = b.standardOptimizeOption(.{}); + const dep_opts = .{ .target = target, .optimize = optimize }; + const exe = b.addExecutable(.{ .name = "zap", // In this case the main source file is merely a path, however, in more // complicated build scripts, this could be a generated file. - .root_source_file = .{ .path = "src/main.zig" }, + .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); - //exe.addPackagePath("random", "src/random.zig"); - const zap = b.dependency("zap", .{ .target = target, .optimize = optimize, .openssl = false, // set to true to enable TLS support }); - exe.addModule("zap", zap.module("zap")); - const pg = b.dependency("pg", .{ - .target = target, - .optimize = optimize, - }); - exe.addModule("pg", pg.module("pg")); + var modules = ModuleMap.init(allocator); + defer modules.deinit(); - const dig = b.dependency("dig", .{ - .target = target, - .optimize = optimize, - }); - exe.addModule("dns", dig.module("dns")); + const zap_module = b.dependency("zap", dep_opts).module("zap"); + const pg_module = b.dependency("pg", dep_opts).module("pg"); + const dig_module = b.dependency("dig", dep_opts).module("dns"); + + try modules.put("zap", zap_module); + try modules.put("pg", pg_module); + try modules.put("dig", dig_module); - // const mustache = b.dependency("mustache", .{ - // .target = target, - // .optimize = optimize, - // }); - // exe.addModule("mustache", mustache.module("mustache")); + // // Expose this as a module that others can import + exe.root_module.addImport("zap", zap_module); + exe.root_module.addImport("pg", pg_module); + exe.root_module.addImport("dig", dig_module); exe.linkLibrary(zap.artifact("facil.io")); @@ -84,7 +84,7 @@ pub fn build(b: *std.Build) void { // Creates a step for unit testing. This only builds the test executable // but does not run it. const unit_tests = b.addTest(.{ - .root_source_file = .{ .path = "src/main.zig" }, + .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); diff --git a/frameworks/Zig/zap/build.zig.zon b/frameworks/Zig/zap/build.zig.zon index 3abfe719e55..871e73b7f76 100644 --- a/frameworks/Zig/zap/build.zig.zon +++ b/frameworks/Zig/zap/build.zig.zon @@ -1,21 +1,13 @@ -.{ - .name = "Zap testing", - .version = "0.1.0", - - .dependencies = .{ - // zap v0.5.1 - .zap = .{ - .url = "https://github.com/zigzap/zap/archive/refs/tags/v0.5.1.tar.gz", - .hash = "1220d4802fb09d4e99c0e7265f90d6f3cfdc3e5e31c1b05f0924ee2dd26d9d6dbbf4", - }, - .pg = .{ - .url = "https://github.com/karlseguin/pg.zig/archive/f3f4a0b3b9996bfb1bf9bd0bdd0d73b36e915a86.tar.gz", - .hash = "1220337202642ee66408a35f254549f22cf3a096c6fa6c28e6f87a0161d5a6c0f4ab" - }, - .dig = .{ - .url = "https://github.com/lun-4/zigdig/archive/2ec407ec3c7f347e747717977958e9ba339eb82f.tar.gz", - .hash = "1220dfdb3089dfe9a4e4bc1226fcff08d91d0c0853f287d98d8b81270da251790331" - }, - - } -} \ No newline at end of file +.{ .name = "Zap testing", .version = "0.1.1", .paths = .{ + "build.zig", + "build.zig.zon", + "src", +}, .dependencies = .{ + .zap = .{ + .url = "https://github.com/zigzap/zap/archive/refs/tags/v0.8.0.tar.gz", + .hash = "12209936c3333b53b53edcf453b1670babb9ae8c2197b1ca627c01e72670e20c1a21", + }, + .pg = .{ .url = "https://github.com/karlseguin/pg.zig/archive/239a4468163a49d8c0d03285632eabe96003e9e2.tar.gz", + .hash = "1220a1d7e51e2fa45e547c76a9e099c09d06e14b0b9bfc6baa89367f56f1ded399a0" }, + .dig = .{ .url = "https://github.com/lun-4/zigdig/archive/a54c85c26aa83c64ee81e3ee1818890be5cbed0b.tar.gz", .hash = "1220f078ab62d1328339504f9122dc4d241be30ada451628d78b8a3bf5bb9be1dcba" }, +} } diff --git a/frameworks/Zig/zap/run.sh b/frameworks/Zig/zap/run.sh index 95c2266e8bd..b4698a15de1 100644 --- a/frameworks/Zig/zap/run.sh +++ b/frameworks/Zig/zap/run.sh @@ -1,3 +1,3 @@ -echo "Waiting for ZAP to start..." +echo "Waiting for ZAP framework to start..." zap \ No newline at end of file diff --git a/frameworks/Zig/zap/src/endpoints.zig b/frameworks/Zig/zap/src/endpoints.zig index aeeffbf4e0a..3492e686591 100644 --- a/frameworks/Zig/zap/src/endpoints.zig +++ b/frameworks/Zig/zap/src/endpoints.zig @@ -64,27 +64,27 @@ pub const FortunesEndpoint = struct { defer conn.release(); var rows = try conn.query("SELECT id, message FROM Fortune", .{}); - rows.deinit(); + defer rows.deinit(); var fortunes = std.ArrayList(Fortune).init(middleware.SharedAllocator.getAllocator()); defer fortunes.deinit(); while (try rows.next()) |row| { - var fortune = Fortune{ .id = row.get(i32, 0), .message = row.get([]const u8, 1) }; - _ = try fortunes.append(fortune); + const fortune = Fortune{ .id = row.get(i32, 0), .message = row.get([]const u8, 1) }; + try fortunes.append(fortune); } - var fortune = Fortune{ .id = 0, .message = "Additional fortune added at request time." }; - _ = try fortunes.append(fortune); + const fortune = Fortune{ .id = 0, .message = "Additional fortune added at request time." }; + try fortunes.append(fortune); - var fortunes_slice = try fortunes.toOwnedSlice(); + const fortunes_slice = try fortunes.toOwnedSlice(); std.mem.sort(Fortune, fortunes_slice, {}, cmpFortuneByMessage); return fortunes_slice; } fn getFortunesHtml(self: *Self, pool: *pg.Pool) ![]const u8 { - var fortunes = try getFortunes(pool); + const fortunes = try getFortunes(pool); self.mutex.lock(); const ret = self.mustache.build(.{ .fortunes = fortunes }); @@ -95,7 +95,7 @@ pub const FortunesEndpoint = struct { // std.debug.print("mustache output {s}\n", .{raw}); - var html = try deescapeHtml(raw); + const html = try deescapeHtml(raw); // std.debug.print("html output {s}\n", .{html}); @@ -103,7 +103,7 @@ pub const FortunesEndpoint = struct { } pub fn get(ep: *zap.Endpoint, req: zap.Request) void { - const self = @fieldParentPtr(Self, "ep", ep); + const self: *FortunesEndpoint = @fieldParentPtr("ep", ep); if (!checkPath(ep, req)) return; @@ -118,7 +118,7 @@ pub const FortunesEndpoint = struct { } } - var fortunes_html = getFortunesHtml(self, pool) catch return; + const fortunes_html = getFortunesHtml(self, pool) catch return; req.sendBody(fortunes_html) catch return; @@ -146,7 +146,7 @@ pub const DbEndpoint = struct { } pub fn get(ep: *zap.Endpoint, req: zap.Request) void { - const self = @fieldParentPtr(Self, "ep", ep); + const self: *DbEndpoint = @fieldParentPtr("ep", ep); if (!checkPath(ep, req)) return; @@ -177,14 +177,13 @@ pub const DbEndpoint = struct { var conn = pool.acquire() catch return; defer conn.release(); - var row_result = conn.row("SELECT id, randomNumber FROM World WHERE id = $1", .{random_number}) catch |err| { + const row_result = conn.row("SELECT id, randomNumber FROM World WHERE id = $1", .{random_number}) catch |err| { std.debug.print("Error querying database: {}\n", .{err}); return; }; var row = row_result.?; - defer row.deinit(); - var world = World{ .id = row.get(i32, 0), .randomNumber = row.get(i32, 1) }; + const world = World{ .id = row.get(i32, 0), .randomNumber = row.get(i32, 1) }; var buf: [100]u8 = undefined; var json_to_send: []const u8 = undefined; @@ -218,7 +217,7 @@ pub const PlaintextEndpoint = struct { } pub fn get(ep: *zap.Endpoint, req: zap.Request) void { - const self = @fieldParentPtr(Self, "ep", ep); + const self: *PlaintextEndpoint = @fieldParentPtr("ep", ep); _ = self; if (!checkPath(ep, req)) return; @@ -248,14 +247,14 @@ pub const JsonEndpoint = struct { } pub fn get(ep: *zap.Endpoint, req: zap.Request) void { - const self = @fieldParentPtr(Self, "ep", ep); + const self: *JsonEndpoint = @fieldParentPtr("ep", ep); _ = self; if (!checkPath(ep, req)) return; req.setContentType(.JSON) catch return; - var message = Message{ .message = "Hello, World!" }; + const message = Message{ .message = "Hello, World!" }; var buf: [100]u8 = undefined; var json_to_send: []const u8 = undefined; diff --git a/frameworks/Zig/zap/src/main.zig b/frameworks/Zig/zap/src/main.zig index 489fb5d5b7e..0c66a7639bb 100644 --- a/frameworks/Zig/zap/src/main.zig +++ b/frameworks/Zig/zap/src/main.zig @@ -21,16 +21,12 @@ pub fn main() !void { .child_allocator = gpa.allocator(), }; - var allocator = tsa.allocator(); + const allocator = tsa.allocator(); var pg_pool = try pool.initPool(allocator); defer pg_pool.deinit(); - var rnd = std.rand.DefaultPrng.init(blk: { - var seed: u64 = undefined; - try std.os.getrandom(std.mem.asBytes(&seed)); - break :blk seed; - }); + var prng = std.rand.DefaultPrng.init(@as(u64, @bitCast(std.time.milliTimestamp()))); middleware.SharedAllocator.init(allocator); @@ -66,7 +62,7 @@ pub fn main() !void { ); var headerHandler = middleware.HeaderMiddleWare.init(dbEndpointHandler.getHandler()); - var prngHandler = middleware.PrngMiddleWare.init(headerHandler.getHandler(), &rnd); + var prngHandler = middleware.RandomMiddleWare.init(headerHandler.getHandler(), &prng); var pgHandler = middleware.PgMiddleWare.init(prngHandler.getHandler(), pg_pool); var listener = try zap.Middleware.Listener(middleware.Context).init( @@ -92,4 +88,3 @@ pub fn main() !void { .workers = 1, }); } - diff --git a/frameworks/Zig/zap/src/middleware.zig b/frameworks/Zig/zap/src/middleware.zig index 20c01b7ffde..99fb9255c0c 100644 --- a/frameworks/Zig/zap/src/middleware.zig +++ b/frameworks/Zig/zap/src/middleware.zig @@ -22,7 +22,7 @@ pub const SharedAllocator = struct { // create a combined context struct pub const Context = struct { - prng: ?PrngMiddleWare.Prng = null, + prng: ?RandomMiddleWare.Prng = null, pg: ?PgMiddleWare.Pg = null, }; @@ -47,7 +47,7 @@ pub const HeaderMiddleWare = struct { // note that the first parameter is of type *Handler, not *Self !!! pub fn onRequest(handler: *Handler, req: zap.Request, context: *Context) bool { // this is how we would get our self pointer - var self = @fieldParentPtr(Self, "handler", handler); + const self: *Self = @fieldParentPtr("handler", handler); _ = self; req.setHeader("Server", "Zap") catch return false; @@ -57,7 +57,7 @@ pub const HeaderMiddleWare = struct { } }; -pub const PrngMiddleWare = struct { +pub const RandomMiddleWare = struct { handler: Handler, rnd: *std.rand.DefaultPrng, @@ -83,7 +83,7 @@ pub const PrngMiddleWare = struct { pub fn onRequest(handler: *Handler, req: zap.Request, context: *Context) bool { // this is how we would get our self pointer - var self = @fieldParentPtr(Self, "handler", handler); + const self: *RandomMiddleWare = @fieldParentPtr("handler", handler); context.prng = Prng{ .rnd = self.rnd }; @@ -118,7 +118,7 @@ pub const PgMiddleWare = struct { pub fn onRequest(handler: *Handler, req: zap.Request, context: *Context) bool { // this is how we would get our self pointer - var self = @fieldParentPtr(Self, "handler", handler); + const self: *Self = @fieldParentPtr("handler", handler); // do our work: fill in the user field of the context context.pg = Pg{ .pool = self.pool }; diff --git a/frameworks/Zig/zap/src/pool.zig b/frameworks/Zig/zap/src/pool.zig index 7241780a464..84df32104b0 100644 --- a/frameworks/Zig/zap/src/pool.zig +++ b/frameworks/Zig/zap/src/pool.zig @@ -1,7 +1,7 @@ const std = @import("std"); -const pg = @import("pg"); const regex = @import("regex"); -const dns = @import("dns"); +const dns = @import("dig"); +const pg = @import("pg"); const Allocator = std.mem.Allocator; const Pool = pg.Pool; @@ -9,31 +9,22 @@ const ArrayList = std.ArrayList; const Regex = regex.Regex; pub fn initPool(allocator: Allocator) !*pg.Pool { - const info = try parsePostgresConnStr(); - std.debug.print("Cconnection info: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database }); - - const hostname = std.os.getenv("PG_HOST") orelse "localhost"; - var addresses = try dns.helpers.getAddressList(hostname, allocator); - defer addresses.deinit(); - - var hostAddress = std.net.Address.parseIp("127.0.0.1", 0) catch unreachable; - - for (addresses.addrs) |address| { - hostAddress = address; - } - - std.debug.print("tfb hostname {}\n", .{hostAddress.in}); - - const host = try addressAsString(hostAddress); - - var pg_pool = try Pool.init(allocator, .{ .size = 28, .connect = .{ - .port = info.port, - .host = host, - }, .auth = .{ - .username = info.username, - .database = info.database, - .password = info.password, - }, .timeout = 10_000,}); + const info = try parsePostgresConnStr(allocator); + std.debug.print("Connection: {s}:{s}@{s}:{d}/{s}\n", .{ info.username, info.password, info.hostname, info.port, info.database }); + + const pg_pool = try Pool.init(allocator, .{ + .size = 28, + .connect = .{ + .port = info.port, + .host = info.hostname, + }, + .auth = .{ + .username = info.username, + .database = info.database, + .password = info.password, + }, + .timeout = 10_000, + }); return pg_pool; } @@ -67,12 +58,32 @@ fn addressAsString(address: std.net.Address) ![]const u8 { return output; } -fn parsePostgresConnStr() !ConnectionInfo { +fn parsePostgresConnStr(allocator: Allocator) !ConnectionInfo { + const pg_port = try getEnvVar(allocator, "PG_PORT", "5432"); + std.debug.print("tfb port {s}\n", .{pg_port}); + var port = try std.fmt.parseInt(u16, pg_port, 0); + + if (port == 0) { + port = 5432; + } + return ConnectionInfo{ - .username = std.os.getenv("PG_USER") orelse "benchmarkdbuser", - .password = std.os.getenv("PG_PASS") orelse "benchmarkdbpass", - .hostname = std.os.getenv("PG_HOST") orelse "localhost", // , - .port = try std.fmt.parseInt(u16, std.os.getenv("PG_PORT") orelse "5432", 0), - .database = std.os.getenv("PG_DB") orelse "hello_world", + .username = try getEnvVar(allocator, "PG_USER", "benchmarkdbuser"), + .password = try getEnvVar(allocator, "PG_PASS", "benchmarkdbpass"), + .hostname = try getEnvVar(allocator, "PG_HOST", "localhost"), + .port = port, + .database = try getEnvVar(allocator, "PG_DB", "hello_world"), }; } + +fn getEnvVar(allocator: Allocator, name: []const u8, default: []const u8) ![]const u8 { + const env_var = std.process.getEnvVarOwned(allocator, name) catch |err| switch (err) { + error.EnvironmentVariableNotFound => return default, + error.OutOfMemory => return err, + error.InvalidWtf8 => return err, + }; + + if (env_var.len == 0) return default; + + return env_var; +} diff --git a/frameworks/Zig/zap/zap.dockerfile b/frameworks/Zig/zap/zap.dockerfile index 580f037bcef..9aa8a4109ae 100644 --- a/frameworks/Zig/zap/zap.dockerfile +++ b/frameworks/Zig/zap/zap.dockerfile @@ -1,42 +1,46 @@ -#FROM ziglang/static-base:llvm15-aarch64-3 as build -FROM buddyspencer/ziglang:0.11.0-r3 as build +FROM fedora:40 AS build WORKDIR /zap +ENV PG_USER=benchmarkdbuser +ENV PG_PASS=benchmarkdbpass +ENV PG_DB=hello_world +ENV PG_HOST=tfb-database +ENV PG_PORT=5432 + COPY src src +COPY run.sh run.sh COPY build.zig.zon build.zig.zon COPY build.zig build.zig -RUN apk update -RUN apk add yaml-dev sqlite-dev -RUN apk add bind-tools -RUN apk add --no-cache bash -RUN dig +short localhost | head -n 1 -RUN zig build -Doptimize=ReleaseFast --prefix-exe-dir /usr/bin +RUN dnf install -y zig RUN zig version -RUN ls +# RUN zig build -Doptimize=ReleaseFast +RUN zig build +RUN cp /zap/zig-out/bin/zap /usr/local/bin EXPOSE 3000 CMD ["sh", "run.sh"] -FROM alpine:3.19 +# FROM alpine:3.19 -WORKDIR /zap +# WORKDIR /zap -ENV PG_USER=benchmarkdbuser -ENV PG_PASS=benchmarkdbpass -ENV PG_DB=hello_world -ENV PG_HOST=tfb-database -ENV PG_PORT=5432 +# ENV PG_USER=benchmarkdbuser +# ENV PG_PASS=benchmarkdbpass +# ENV PG_DB=hello_world +# ENV PG_HOST=tfb-database +# ENV PG_PORT=5432 -COPY run.sh run.sh +# RUN apk update +# RUN apk add libc6-compat -RUN apk update +# COPY run.sh run.sh -COPY --from=build /usr/bin/zap /usr/bin/zap +# COPY --from=build /zap/zig-out/bin/zap /usr/local/bin -EXPOSE 3000 +# EXPOSE 3000 -CMD ["sh", "run.sh"] \ No newline at end of file +# CMD ["sh", "run.sh"] \ No newline at end of file From f03d5ee8221a3c68ab9efe7dd2f4f56c29c73320 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 20:11:35 +0000 Subject: [PATCH 33/40] Bump body-parser from 1.19.0 to 1.20.3 in /frameworks/JavaScript/express Bumps [body-parser](https://github.com/expressjs/body-parser) from 1.19.0 to 1.20.3. - [Release notes](https://github.com/expressjs/body-parser/releases) - [Changelog](https://github.com/expressjs/body-parser/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/body-parser/compare/1.19.0...1.20.3) --- updated-dependencies: - dependency-name: body-parser dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- frameworks/JavaScript/express/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/JavaScript/express/package.json b/frameworks/JavaScript/express/package.json index 32ea58ae528..09723c74dd8 100644 --- a/frameworks/JavaScript/express/package.json +++ b/frameworks/JavaScript/express/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "dependencies": { - "body-parser": "1.19.0", + "body-parser": "1.20.3", "dateformat": "3.0.3", "escape-html": "1.0.3", "express": "4.18.2", From 844094b11d96033697b39bad81c791c88021fe17 Mon Sep 17 00:00:00 2001 From: Petrik de Heus Date: Thu, 12 Sep 2024 18:06:27 +0200 Subject: [PATCH 34/40] [rails] Delete remaining unused middleware (#9259) The following middleware is unused for the benchmark: - Callbacks - Rack::TempfileReaper The following middleware is already disabled in production by default, so they don't need to be deleted: - ActionDispatch::HostAuthorization - ActionDispatch::Static The remaining middleware are: - ActiveSupport::Cache::Strategy::LocalCache::Middleware - Hello::Application.routes Also sort the middleware. The middleware can be checked using the following command: SECRET_KEY_BASE_DUMMY=1 RAILS_ENV=production_mysql bin/rails middleware --- frameworks/Ruby/rails/config/application.rb | 31 +++++++++---------- .../rails/config/environments/production.rb | 3 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/frameworks/Ruby/rails/config/application.rb b/frameworks/Ruby/rails/config/application.rb index 7e3e1d4af56..75a12720345 100644 --- a/frameworks/Ruby/rails/config/application.rb +++ b/frameworks/Ruby/rails/config/application.rb @@ -30,27 +30,26 @@ class Application < Rails::Application config.action_dispatch.default_headers.merge!('Server' => 'WebServer') - config.middleware.delete ActionDispatch::HostAuthorization - config.middleware.delete Rack::Sendfile - config.middleware.delete ActionDispatch::Static + config.middleware.delete ActionDispatch::Callbacks + config.middleware.delete ActionDispatch::ContentSecurityPolicy::Middleware + config.middleware.delete ActionDispatch::Cookies + config.middleware.delete ActionDispatch::DebugExceptions config.middleware.delete ActionDispatch::Executor - config.middleware.delete Rack::Runtime - config.middleware.delete Rack::MethodOverride - config.middleware.delete ActionDispatch::RequestId + config.middleware.delete ActionDispatch::Flash + config.middleware.delete ActionDispatch::PermissionsPolicy::Middleware + config.middleware.delete ActionDispatch::Reloader config.middleware.delete ActionDispatch::RemoteIp - config.middleware.delete Rails::Rack::Logger + config.middleware.delete ActionDispatch::RequestId + config.middleware.delete ActionDispatch::Session::CookieStore config.middleware.delete ActionDispatch::ShowExceptions - config.middleware.delete ActionDispatch::DebugExceptions - config.middleware.delete ActionDispatch::ActionableExceptions - config.middleware.delete ActionDispatch::Reloader config.middleware.delete ActiveRecord::Migration::CheckPending - config.middleware.delete ActionDispatch::Cookies - config.middleware.delete ActionDispatch::Session::CookieStore - config.middleware.delete ActionDispatch::Flash - config.middleware.delete ActionDispatch::ContentSecurityPolicy::Middleware - config.middleware.delete ActionDispatch::PermissionsPolicy::Middleware - config.middleware.delete Rack::Head config.middleware.delete Rack::ConditionalGet config.middleware.delete Rack::ETag + config.middleware.delete Rack::Head + config.middleware.delete Rack::MethodOverride + config.middleware.delete Rack::Runtime + config.middleware.delete Rack::Sendfile + config.middleware.delete Rack::TempfileReaper + config.middleware.delete Rails::Rack::Logger end end diff --git a/frameworks/Ruby/rails/config/environments/production.rb b/frameworks/Ruby/rails/config/environments/production.rb index f9de0f173d6..45b097c9f04 100644 --- a/frameworks/Ruby/rails/config/environments/production.rb +++ b/frameworks/Ruby/rails/config/environments/production.rb @@ -21,7 +21,8 @@ # config.require_master_key = true # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead. - # config.public_file_server.enabled = false + # This disables the ActionDispatch::Static middleware. + config.public_file_server.enabled = false # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.asset_host = "http://assets.example.com" From a329357a317652fad2f7ac2c0bde2e384264fceb Mon Sep 17 00:00:00 2001 From: Redkale Date: Fri, 13 Sep 2024 00:06:42 +0800 Subject: [PATCH 35/40] Update maven:3.9.6 (#9257) * Update maven:3.9.6 * Update graalvm:22.0.2 * Update graalvm-ce:22.3.3 * Update native-image-community:22.0.2 * Update jdk-community:22.0.2 * Update graalvm-ce:ol9 * Update graalvm-ce:ol9 * Update config * Update config * Update config * Update config * Update FortuneRender * Update Redkale-2.8.0 --- frameworks/Java/redkale/BenchmarkService.java | 5 +++ frameworks/Java/redkale/conf/application.xml | 8 ++--- .../Java/redkale/conf/source.properties | 5 +-- frameworks/Java/redkale/pom-jdbc.xml | 9 +++--- frameworks/Java/redkale/pom-pgclient.xml | 9 +++--- frameworks/Java/redkale/pom.xml | 8 ++--- .../Java/redkale/redkale-block.dockerfile | 2 +- .../Java/redkale/redkale-graalvm.dockerfile | 4 +-- .../Java/redkale/redkale-jdbc.dockerfile | 2 +- .../Java/redkale/redkale-native.dockerfile | 10 +++--- .../Java/redkale/redkale-pgclient.dockerfile | 2 +- frameworks/Java/redkale/redkale.dockerfile | 2 +- .../redkalex/benchmark/BenchmarkService.java | 9 ++++-- .../org/redkalex/benchmark/FortuneRender.java | 31 ++++++++++--------- 14 files changed, 58 insertions(+), 48 deletions(-) diff --git a/frameworks/Java/redkale/BenchmarkService.java b/frameworks/Java/redkale/BenchmarkService.java index 06e760bf879..39e9956a75d 100644 --- a/frameworks/Java/redkale/BenchmarkService.java +++ b/frameworks/Java/redkale/BenchmarkService.java @@ -12,6 +12,7 @@ import org.redkale.net.http.*; import org.redkale.service.AbstractService; import org.redkale.source.DataSource; +import org.redkale.util.AnyValue; /** * 测试redkale-jdbc, 需要覆盖到原BenchmarkService @@ -26,6 +27,10 @@ public class BenchmarkService extends AbstractService { @Resource private DataSource source; + public void init(AnyValue conf) { + source.finds(CachedWorld.class, 1); + } + @NonBlocking @RestMapping(auth = false) public byte[] plaintext() { diff --git a/frameworks/Java/redkale/conf/application.xml b/frameworks/Java/redkale/conf/application.xml index d7157c9f8d3..aa535805113 100644 --- a/frameworks/Java/redkale/conf/application.xml +++ b/frameworks/Java/redkale/conf/application.xml @@ -4,19 +4,19 @@ - - + - - + + + diff --git a/frameworks/Java/redkale/conf/source.properties b/frameworks/Java/redkale/conf/source.properties index 9efb8cd4158..f88e22a2a12 100644 --- a/frameworks/Java/redkale/conf/source.properties +++ b/frameworks/Java/redkale/conf/source.properties @@ -4,5 +4,6 @@ redkale.datasource[].url = jdbc:postgresql://tfb-database:5432/hello_world redkale.datasource[].user = benchmarkdbuser redkale.datasource[].password = benchmarkdbpass -redkale.datasource[].warnslowms = 0 -redkale.datasource[].errorslowms = 0 +redkale.datasource[].non-blocking = true +redkale.datasource[].warn-slowms = 0 +redkale.datasource[].error-slowms = 0 diff --git a/frameworks/Java/redkale/pom-jdbc.xml b/frameworks/Java/redkale/pom-jdbc.xml index 93df4fb9464..e617e4e4059 100644 --- a/frameworks/Java/redkale/pom-jdbc.xml +++ b/frameworks/Java/redkale/pom-jdbc.xml @@ -7,12 +7,12 @@ org.redkale.boot.Application - 2.9.0-SNAPSHOT + 2.8.0-SNAPSHOT 1.3.0-SNAPSHOT - 42.6.0 + 42.7.2 UTF-8 - 18 - 18 + 21 + 21 @@ -77,7 +77,6 @@ UTF-8 -parameters - --enable-preview true diff --git a/frameworks/Java/redkale/pom-pgclient.xml b/frameworks/Java/redkale/pom-pgclient.xml index 1e7315a9ff2..47f212a3053 100644 --- a/frameworks/Java/redkale/pom-pgclient.xml +++ b/frameworks/Java/redkale/pom-pgclient.xml @@ -7,13 +7,13 @@ org.redkale.boot.Application - 2.9.0-SNAPSHOT - 1.3.0-SNAPSHOT + 2.8.0-SNAPSHOT + 1.2.0-SNAPSHOT 4.5.8 2.1 UTF-8 - 18 - 18 + 21 + 21 @@ -84,7 +84,6 @@ UTF-8 -parameters - --enable-preview true
diff --git a/frameworks/Java/redkale/pom.xml b/frameworks/Java/redkale/pom.xml index 78ffcbdd93b..8844a8b7aff 100644 --- a/frameworks/Java/redkale/pom.xml +++ b/frameworks/Java/redkale/pom.xml @@ -7,11 +7,11 @@ org.redkale.boot.Application - 2.9.0-SNAPSHOT - 1.3.0-SNAPSHOT + 2.8.0-SNAPSHOT + 1.2.0-SNAPSHOT UTF-8 - 11 - 11 + 21 + 21 diff --git a/frameworks/Java/redkale/redkale-block.dockerfile b/frameworks/Java/redkale/redkale-block.dockerfile index 36d75c9db4d..b163c60e53f 100644 --- a/frameworks/Java/redkale/redkale-block.dockerfile +++ b/frameworks/Java/redkale/redkale-block.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf diff --git a/frameworks/Java/redkale/redkale-graalvm.dockerfile b/frameworks/Java/redkale/redkale-graalvm.dockerfile index 25ad428f6c8..0e3a9a4a597 100644 --- a/frameworks/Java/redkale/redkale-graalvm.dockerfile +++ b/frameworks/Java/redkale/redkale-graalvm.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf @@ -6,7 +6,7 @@ COPY pom.xml pom.xml RUN mvn package -q -FROM ghcr.io/graalvm/jdk-community:21.0.0 +FROM ghcr.io/graalvm/jdk-community:22.0.2 WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar diff --git a/frameworks/Java/redkale/redkale-jdbc.dockerfile b/frameworks/Java/redkale/redkale-jdbc.dockerfile index 4588baf43f1..b39997adf5f 100644 --- a/frameworks/Java/redkale/redkale-jdbc.dockerfile +++ b/frameworks/Java/redkale/redkale-jdbc.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf diff --git a/frameworks/Java/redkale/redkale-native.dockerfile b/frameworks/Java/redkale/redkale-native.dockerfile index ae8e0cd7895..56fa1921f96 100644 --- a/frameworks/Java/redkale/redkale-native.dockerfile +++ b/frameworks/Java/redkale/redkale-native.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf @@ -6,15 +6,15 @@ COPY pom.xml pom.xml RUN mvn package -q -FROM ghcr.io/graalvm/graalvm-ce:ol9-java17-22.3.3 -RUN gu install native-image +FROM ghcr.io/graalvm/native-image-community:22.0.2 as native WORKDIR /redkale COPY conf conf COPY --from=maven /redkale/target/redkale-benchmark-1.0.0.jar redkale-benchmark.jar - RUN native-image -H:+ReportExceptionStackTraces --report-unsupported-elements-at-runtime -jar redkale-benchmark.jar -RUN ls -lh +FROM ghcr.io/graalvm/jdk-community:22.0.2 +WORKDIR /redkale +COPY --from=native /redkale/redkale-benchmark redkale-benchmark EXPOSE 8080 diff --git a/frameworks/Java/redkale/redkale-pgclient.dockerfile b/frameworks/Java/redkale/redkale-pgclient.dockerfile index fdc4786a478..6da37e715c5 100644 --- a/frameworks/Java/redkale/redkale-pgclient.dockerfile +++ b/frameworks/Java/redkale/redkale-pgclient.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf diff --git a/frameworks/Java/redkale/redkale.dockerfile b/frameworks/Java/redkale/redkale.dockerfile index 8982ae3b16d..4bb09a8dd56 100644 --- a/frameworks/Java/redkale/redkale.dockerfile +++ b/frameworks/Java/redkale/redkale.dockerfile @@ -1,4 +1,4 @@ -FROM maven:3.8.6-openjdk-18-slim as maven +FROM maven:3.9.6-amazoncorretto-21-debian as maven WORKDIR /redkale COPY src src COPY conf conf diff --git a/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/BenchmarkService.java b/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/BenchmarkService.java index 20f816362d2..48af592f928 100644 --- a/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/BenchmarkService.java +++ b/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/BenchmarkService.java @@ -13,6 +13,7 @@ import org.redkale.net.http.*; import org.redkale.service.AbstractService; import org.redkale.source.DataSource; +import org.redkale.util.AnyValue; /** * @@ -27,6 +28,10 @@ public class BenchmarkService extends AbstractService { @Resource private DataSource source; + public void init(AnyValue conf) { + source.finds(CachedWorld.class, 1); + } + @RestMapping(auth = false) public byte[] plaintext() { return helloBytes; @@ -53,8 +58,8 @@ public CompletableFuture> updates(int q) { IntStream ids = ThreadLocalRandom.current().ints(size, 1, 10001); int[] newNumbers = ThreadLocalRandom.current().ints(size, 1, 10001).toArray(); return source.findsListAsync(World.class, ids.boxed()) - .thenCompose(words -> source.updateAsync(World.updateNewNumbers(words, newNumbers)) - .thenApply(v -> words)); + .thenCompose(words -> source.updateAsync(World.updateNewNumbers(words, newNumbers)) + .thenApply(v -> words)); } @RestMapping(auth = false) diff --git a/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/FortuneRender.java b/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/FortuneRender.java index 201c58bc741..651864d0da5 100644 --- a/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/FortuneRender.java +++ b/frameworks/Java/redkale/src/main/java/org/redkalex/benchmark/FortuneRender.java @@ -7,6 +7,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.function.Function; import org.redkale.convert.Convert; import org.redkale.net.http.*; import org.redkale.util.*; @@ -19,7 +20,9 @@ public class FortuneRender implements org.redkale.net.http.HttpRender { private static final String contentType = "text/html; charset=utf-8"; - private static final byte[] text1 = "Fortunes".getBytes(StandardCharsets.UTF_8); + private static final byte[] text1 = + "Fortunes
idmessage
" + .getBytes(StandardCharsets.UTF_8); private static final byte[] text2 = "
idmessage
".getBytes(StandardCharsets.UTF_8); @@ -29,9 +32,9 @@ public class FortuneRender implements org.redkale.net.http.HttpRender { private static final byte[] text5 = "
".getBytes(StandardCharsets.UTF_8); - private final ThreadLocal localByteArray = ThreadLocal.withInitial(() -> new ByteArray(1280)); + private static final String arrayName = "fortuneByteArray"; - private final ThreadLocal localTmpArray = ThreadLocal.withInitial(() -> new ByteArray(128)); + private static final Function arrayFunc = s -> new ByteArray(1280); private byte[][] idBytesCache; @@ -53,12 +56,11 @@ public void init(HttpContext context, AnyValue config) { @Override public void renderTo(HttpRequest request, HttpResponse response, Convert convert, HttpScope scope) { - ByteArray array = localByteArray.get().clear(); + ByteArray array = request.getSubobjectIfAbsent(arrayName, arrayFunc).clear(); array.put(text1); - ByteArray tmp = localTmpArray.get(); for (Fortune item : (List) scope.getReferObj()) { - array.put(text2).put(escapeId(item.getId())) - .put(text3).put(escapeMessage(tmp, item.getMessage())).put(text4); + ByteArray msg = request.getSubobjectIfAbsent(item.getMessage(), this::escapeMessage); + array.put(text2).put(escapeId(item.getId())).put(text3).put(msg).put(text4); } array.put(text5); response.finish(contentType, array); @@ -72,23 +74,22 @@ private byte[] escapeId(int id) { } } - private ByteArray escapeMessage(ByteArray tmp, String message) { - tmp.clear(); + private ByteArray escapeMessage(String message) { + ByteArray array = new ByteArray(128); CharSequence cs = message; for (int i = 0; i < cs.length(); i++) { char c = cs.charAt(i); byte[] bs = c < escapeCache.length ? escapeCache[c] : null; if (bs != null) { - tmp.put(bs); + array.put(bs); } else if (c < 0x80) { - tmp.put((byte) c); + array.put((byte) c); } else if (c < 0x800) { - tmp.put((byte) (0xc0 | (c >> 6)), (byte) (0x80 | (c & 0x3f))); + array.put((byte) (0xc0 | (c >> 6)), (byte) (0x80 | (c & 0x3f))); } else { - tmp.put((byte) (0xe0 | ((c >> 12))), (byte) (0x80 | ((c >> 6) & 0x3f)), (byte) (0x80 | (c & 0x3f))); + array.put((byte) (0xe0 | (c >> 12)), (byte) (0x80 | ((c >> 6) & 0x3f)), (byte) (0x80 | (c & 0x3f))); } } - return tmp; + return array; } - } From aac290b65e3178e330b8ef2948b953023d0ba4f7 Mon Sep 17 00:00:00 2001 From: SaltyAom Date: Thu, 12 Sep 2024 23:06:55 +0700 Subject: [PATCH 36/40] [Elysia] add compiled configuration, use cluster mode, optimize performance (#9251) * feat(elysia): use cluster mode, static resource, add compiled mode * feat(elysia): use imperative for-loop instead of map to optimize performance --- .../TypeScript/elysia/benchmark_config.json | 23 +++++++ frameworks/TypeScript/elysia/bun.lockb | Bin 4963 -> 3513 bytes .../elysia/elysia-compiled.dockerfile | 15 +++++ .../elysia/elysia-postgres.dockerfile | 6 +- .../elysia/elysia-smol-postgres.dockerfile | 8 +-- .../TypeScript/elysia/elysia.dockerfile | 2 +- frameworks/TypeScript/elysia/package.json | 8 +-- frameworks/TypeScript/elysia/spawn.ts | 18 ------ .../TypeScript/elysia/src/db-handlers.ts | 59 +++++++++--------- frameworks/TypeScript/elysia/src/index.ts | 39 +++++------- frameworks/TypeScript/elysia/src/postgres.ts | 37 ++++++----- frameworks/TypeScript/elysia/src/server.ts | 20 ++++++ 12 files changed, 133 insertions(+), 102 deletions(-) create mode 100644 frameworks/TypeScript/elysia/elysia-compiled.dockerfile delete mode 100644 frameworks/TypeScript/elysia/spawn.ts create mode 100644 frameworks/TypeScript/elysia/src/server.ts diff --git a/frameworks/TypeScript/elysia/benchmark_config.json b/frameworks/TypeScript/elysia/benchmark_config.json index 1a0652745db..04e9073cbe8 100755 --- a/frameworks/TypeScript/elysia/benchmark_config.json +++ b/frameworks/TypeScript/elysia/benchmark_config.json @@ -62,6 +62,29 @@ "display_name": "Elysia [smol] [PostgreSQL]", "notes": "", "versus": "nodejs" + }, + "compiled": { + "json_url": "/json", + "plaintext_url": "/plaintext", + "db_url": "/db", + "query_url": "/queries?queries=", + "update_url": "/updates?queries=", + "fortune_url": "/fortunes", + "port": 8080, + "approach": "Realistic", + "classification": "Micro", + "database": "Postgres", + "framework": "elysia", + "language": "TypeScript", + "flavor": "None", + "orm": "Raw", + "platform": "bun", + "webserver": "None", + "os": "Linux", + "database_os": "Linux", + "display_name": "Elysia [Compiled]", + "notes": "", + "versus": "nodejs" } } ] diff --git a/frameworks/TypeScript/elysia/bun.lockb b/frameworks/TypeScript/elysia/bun.lockb index 7e29924798c25d30517bcca2ed92c9934b0540fa..0020cf63f06be5b698becc47ddfdaa4336096013 100755 GIT binary patch delta 600 zcmaE?wo`h7p60FYj0cti2jnY#70S<@wUYhy!=#8|`@K(c=FNg#Q4GAFb7*;%tM9Z9tQ%OpSJWAA>c-7io3E-Pr* zAmkua_~S>ViP!UlR`spP4Egq@o7s-P-Y~25@z$=`=bp}N1>vTfS=n|oPIl(%nY@P6 zWwQfU1S8i5sN0WlOitsmlLNW*-+u@IvDtz615^nQ=j44nMq(^LA&}?UfY^c)NB}_u zNJ?q44X*-M2TX`-av87IH6v0%ME^7XX0LGh3YryXFG&mD=j`fqjG-MrOb)?QN3zgZ7n(TZH~PPoV9xrqX(n# zWKTwWUT>gLCP1x>K$>xKAd~iF2SyIYZIe$j+B5!~%*kZW7(Ce%NVZSz1d>-LpJXxz zsSp$dT4fE>2h=M*nUPT)ERz6~0h!1F6lDcs9=OaDpo|qzMg$}Z#C&j>TR<5{pbSX8 z6cDolWwh&AfGiLO0T2z61qA^J5JLkE1qBNO$ZsI~Kr}FT;edeoW?+T*EW&ER@$A#y+c3j#&-(1Fj{V|p-L0h|~^u}4Q zH!s(nv5aX~)1>wHX4jR>WZc}!vYWAMZzKcK5YK?wsa7tVyTPpwIduTePB+$K|; z;8>)+%D@%n!bcjYgx?Y<#hI^804q5N78->Zw>^>Li~@#=O|_d$k7uR4u8PdJ
Qfl|1()92?QpJt!in3HqP~aSWo(a4 zC_BI_Cc1XAVD8s_*Ww}$mO5*7IICPSoQPyFFpge$m~LKz1`}P48=f$ql^;|7u)sE$TVTLi=W0?UKpi43&~(m zbix3OT0oEW^Mxf&T&n^LCohr@YY+*`Fn)W~`i%X!P9W|RKDSm&r-&-{8Rn?No0_^>h&#<{n4qyw|EWjSYI9Y-H2-gBoQUQW3Jd=w! z?48+JrAo}eSe$ImsVD_f z4$}rQaRF4>C%(x^oLbUA5pd>)KPg^VCvBVxeN%vr3}zESYZOxW2$Flrf0(7zzq0_BuOz+70jx_uFFz#}$}BIQ9K|gy3g-bemKW=Sy=F8yo=080;)vj>Vmy(3Q|8=kbMRKOc#%C diff --git a/frameworks/TypeScript/elysia/elysia-compiled.dockerfile b/frameworks/TypeScript/elysia/elysia-compiled.dockerfile new file mode 100644 index 00000000000..73de65fcfa7 --- /dev/null +++ b/frameworks/TypeScript/elysia/elysia-compiled.dockerfile @@ -0,0 +1,15 @@ +FROM oven/bun:1.1 + +EXPOSE 8080 + +COPY . . + +ENV NODE_ENV production + +RUN bun install --production + +ENV DATABASE postgres + +RUN bun run compile + +CMD ["./server"] diff --git a/frameworks/TypeScript/elysia/elysia-postgres.dockerfile b/frameworks/TypeScript/elysia/elysia-postgres.dockerfile index 40ff868c528..68ce83d3325 100644 --- a/frameworks/TypeScript/elysia/elysia-postgres.dockerfile +++ b/frameworks/TypeScript/elysia/elysia-postgres.dockerfile @@ -8,8 +8,8 @@ ENV NODE_ENV production RUN bun install --production -RUN bun run build - ENV DATABASE postgres -CMD ["bun", "spawn.ts"] +RUN bun run build + +CMD ["bun", "./dist/index.js"] diff --git a/frameworks/TypeScript/elysia/elysia-smol-postgres.dockerfile b/frameworks/TypeScript/elysia/elysia-smol-postgres.dockerfile index de7b9d63bb0..fa6c7a7aca7 100644 --- a/frameworks/TypeScript/elysia/elysia-smol-postgres.dockerfile +++ b/frameworks/TypeScript/elysia/elysia-smol-postgres.dockerfile @@ -6,12 +6,12 @@ COPY . . ENV NODE_ENV production -RUN bun install --production - -RUN bun run build +RUN bun install ENV DATABASE postgres +RUN bun run build + RUN sed -i 's/smol = false/smol = true/g' bunfig.toml -CMD ["bun", "spawn.ts"] +CMD ["bun", "./dist/index.js"] diff --git a/frameworks/TypeScript/elysia/elysia.dockerfile b/frameworks/TypeScript/elysia/elysia.dockerfile index 3ed07652df1..f95b8706c6c 100644 --- a/frameworks/TypeScript/elysia/elysia.dockerfile +++ b/frameworks/TypeScript/elysia/elysia.dockerfile @@ -10,4 +10,4 @@ RUN bun install --production RUN bun run build -CMD ["bun", "spawn.ts"] +CMD ["bun", "./dist/index.js"] diff --git a/frameworks/TypeScript/elysia/package.json b/frameworks/TypeScript/elysia/package.json index ba38bf05ee6..c23716506c8 100644 --- a/frameworks/TypeScript/elysia/package.json +++ b/frameworks/TypeScript/elysia/package.json @@ -3,16 +3,16 @@ "version": "0.0.1", "module": "src/index.js", "devDependencies": { - "bun-types": "^1.1.23", "typescript": "^5.5.4" }, "scripts": { "dev": "bun run --watch src/index.ts", "start": "bun run src/index.ts", - "build": "bun build --compile --minify --outfile server src/index.ts" + "build": "bun build --minify --target bun --outdir dist src/index.ts", + "compile": "bun build --compile --minify --target bun --outfile server src/index.ts" }, "dependencies": { - "elysia": "^1.1.6", + "elysia": "^1.1.12", "postgres": "^3.4.4" } -} \ No newline at end of file +} diff --git a/frameworks/TypeScript/elysia/spawn.ts b/frameworks/TypeScript/elysia/spawn.ts deleted file mode 100644 index 3bf8959c230..00000000000 --- a/frameworks/TypeScript/elysia/spawn.ts +++ /dev/null @@ -1,18 +0,0 @@ -const cpus = navigator.hardwareConcurrency; -const buns = new Array(cpus); - -for (let i = 0; i < cpus; i++) { - buns[i] = Bun.spawn(['./server'], { - stdio: ['inherit', 'inherit', 'inherit'], - env: { ...process.env }, - }); -} - -function kill() { - for (const bun of buns) { - bun.kill(); - } -} - -process.on('SIGINT', kill); -process.on('exit', kill); \ No newline at end of file diff --git a/frameworks/TypeScript/elysia/src/db-handlers.ts b/frameworks/TypeScript/elysia/src/db-handlers.ts index d75e91ff1a5..b75ccfdea60 100644 --- a/frameworks/TypeScript/elysia/src/db-handlers.ts +++ b/frameworks/TypeScript/elysia/src/db-handlers.ts @@ -1,64 +1,63 @@ -import Elysia from 'elysia'; -import * as db from './postgres'; -import { Fortune } from './types'; +import { Elysia, t } from "elysia"; +import * as db from "./postgres"; +import { Fortune } from "./types"; -function rand () { - return Math.ceil(Math.random() * 10000) +function rand() { + return Math.ceil(Math.random() * 10000); } -function parseQueriesNumber (q?: string) { - return Math.min(parseInt(q || '1') || 1, 500) +function parseQueriesNumber(q?: string) { + return Math.min(parseInt(q || "1") || 1, 500); } -function renderTemplate (fortunes: Fortune[]) { +function renderTemplate(fortunes: Fortune[]) { const n = fortunes.length; - let html = ''; + let html = ""; for (let i = 0; i < n; i++) { html += `${fortunes[i].id}${Bun.escapeHTML( - fortunes[i].message + fortunes[i].message, )}`; } return `Fortunes${html}
idmessage
`; } -const dbHandlers = new Elysia({ - name: 'db-handlers', -}) - .onAfterHandle(({ set }) => { - set.headers['server'] = 'Elysia'; +export const dbHandlers = new Elysia() + .headers({ + server: "Elysia", }) - - .get('/db', () => db.find(rand())) - - .get('/fortunes', async ({ set }) => { + .get("/db", () => db.find(rand())) + .get("/fortunes", async (c) => { const fortunes = await db.fortunes(); fortunes.push({ id: 0, - message: 'Additional fortune added at request time.', + message: "Additional fortune added at request time.", + }); + + fortunes.sort((a, b) => { + if (a.message < b.message) return -1; + + return 1; }); - fortunes.sort((a, b) => (a.message < b.message ? -1 : 1)); + c.set.headers["content-type"] = "text/html; charset=utf-8"; - set.headers['content-type'] = 'text/html; charset=utf-8'; return renderTemplate(fortunes); }) - - .get('/queries', async ({ query }) => { - const num = parseQueriesNumber(query.queries) + .get("/queries", (c) => { + const num = parseQueriesNumber(c.query.queries); const worldPromises = new Array(num); for (let i = 0; i < num; i++) { worldPromises[i] = db.find(rand()); } - return await Promise.all(worldPromises); + return Promise.all(worldPromises); }) - - .get('/updates', async ({ query }) => { - const num = parseQueriesNumber(query.queries) + .get("/updates", async (c) => { + const num = parseQueriesNumber(c.query.queries); const worldPromises = new Array(num); for (let i = 0; i < num; i++) { @@ -74,5 +73,3 @@ const dbHandlers = new Elysia({ await db.bulkUpdate(worlds); return worlds; }); - -export default dbHandlers; diff --git a/frameworks/TypeScript/elysia/src/index.ts b/frameworks/TypeScript/elysia/src/index.ts index af24275c128..b34edbde4b7 100644 --- a/frameworks/TypeScript/elysia/src/index.ts +++ b/frameworks/TypeScript/elysia/src/index.ts @@ -1,29 +1,20 @@ -import { Elysia } from 'elysia'; -import dbHandlers from './db-handlers'; +import cluster from "node:cluster"; +import os from "node:os"; +import process from "node:process"; -const app = new Elysia({ - serve: { - reusePort: true, - }, -}) - .get('/plaintext', ({ set }) => { - set.headers['server'] = 'Elysia'; - return 'Hello, World!'; - }) +if (cluster.isPrimary) { + console.log(`Primary ${process.pid} is running`); - .get('/json', ({ set }) => { - set.headers = { - 'content-type': 'application/json', - 'server': 'Elysia', - }; + const numCPUs = os.availableParallelism(); + for (let i = 0; i < numCPUs; i++) { + cluster.fork(); + } - return JSON.stringify({ message: 'Hello, World!' }); + cluster.on("exit", (worker) => { + console.log(`worker ${worker.process.pid} died`); + process.exit(1); }); - -if (Bun.env.DATABASE) { - app.use(dbHandlers); +} else { + await import("./server"); + console.log(`Worker ${process.pid} started`); } - -app.listen(8080); - -console.info(`🦊 Elysia is running at ${app.server!.url}`); diff --git a/frameworks/TypeScript/elysia/src/postgres.ts b/frameworks/TypeScript/elysia/src/postgres.ts index 5c9ba1dbcbe..cc6d4389a02 100644 --- a/frameworks/TypeScript/elysia/src/postgres.ts +++ b/frameworks/TypeScript/elysia/src/postgres.ts @@ -1,27 +1,30 @@ -import postgres from 'postgres'; -import { Fortune, World } from './types'; +import postgres from "postgres"; +import { Fortune, World } from "./types"; const sql = postgres({ - host: 'tfb-database', - user: 'benchmarkdbuser', - password: 'benchmarkdbpass', - database: 'hello_world', + host: "tfb-database", + user: "benchmarkdbuser", + password: "benchmarkdbpass", + database: "hello_world", max: 1, }); -export const fortunes = () => - sql`SELECT id, message FROM fortune`; +export const fortunes = () => sql`SELECT id, message FROM fortune`; export const find = (id: number) => sql`SELECT id, randomNumber FROM world WHERE id = ${id}`.then( - (arr) => arr[0] + (arr) => arr[0], ); -export const bulkUpdate = (worlds: World[]) => - 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`; +export const bulkUpdate = (worlds: World[]) => { + worlds = worlds.toSorted((a, b) => a.id - b.id); + + const values = new Array(worlds.length); + for (let i = 0; i < worlds.length; i++) { + values[i] = [worlds[i].id, worlds[i].randomNumber]; + } + + return sql`UPDATE world SET randomNumber = (update_data.randomNumber)::int + FROM (VALUES ${sql(values)}) AS update_data (id, randomNumber) + WHERE world.id = (update_data.id)::int`; +}; diff --git a/frameworks/TypeScript/elysia/src/server.ts b/frameworks/TypeScript/elysia/src/server.ts new file mode 100644 index 00000000000..7c2c46d224d --- /dev/null +++ b/frameworks/TypeScript/elysia/src/server.ts @@ -0,0 +1,20 @@ +import { Elysia } from "elysia"; +import { dbHandlers } from "./db-handlers"; + +const app = new Elysia() + .headers({ + server: "Elysia", + }) + .get("/plaintext", "Hello, World!") + // As state on xiv in https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#requirements + // The serialization to JSON must not be cached; + // the computational effort to serialize an object to JSON must occur within the scope of handling each request. + .get("/json", () => ({ message: "Hello, World!" })) + .use((app) => { + if (Bun.env.DATABASE) app.use(dbHandlers); + + return app; + }) + .listen(8080); + +console.info(`🦊 Elysia is running at ${app.server!.url}`); From 4a7b80c4cdadd6be50f0a1995a19bf6fbc94e4e2 Mon Sep 17 00:00:00 2001 From: Vladimir Shchur Date: Thu, 12 Sep 2024 19:07:09 +0300 Subject: [PATCH 37/40] [F#/Oxpecker] Simplified connection string (should benefit performance as well) (#9255) --- frameworks/FSharp/oxpecker/src/App/Common.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/FSharp/oxpecker/src/App/Common.fs b/frameworks/FSharp/oxpecker/src/App/Common.fs index 0b62abdefee..47a63e2108e 100644 --- a/frameworks/FSharp/oxpecker/src/App/Common.fs +++ b/frameworks/FSharp/oxpecker/src/App/Common.fs @@ -26,7 +26,7 @@ module Common = } [] - 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 ConnectionString = "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;NoResetOnClose=true;Enlist=false;Max Auto Prepare=3" let FortuneComparer = { new IComparer with From 8222e5dea25315164b6aced97125527f0704c724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A5=BF=E4=B8=9C?= Date: Fri, 13 Sep 2024 00:07:32 +0800 Subject: [PATCH 38/40] [Java] Update Solon Version To 2.9.2 (#9260) * Update Solon Version To 2.9.1 * Update Solon Version To 2.9.1 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Jdk To 21 * Update Solon Version To 2.9.2 * Add Solon-Virtual * Remove solon-virtual --- frameworks/Java/solon/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/Java/solon/pom.xml b/frameworks/Java/solon/pom.xml index a9568927908..035ad60951a 100644 --- a/frameworks/Java/solon/pom.xml +++ b/frameworks/Java/solon/pom.xml @@ -5,7 +5,7 @@ org.noear solon-parent - 2.9.1 + 2.9.2 hello @@ -26,7 +26,7 @@ org.noear - solon.serialization.snack3 + solon.serialization.fastjson2 ${solon.version} From 64398bce241937e42ab2a212f621f0c3fb0ef9d5 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Fri, 13 Sep 2024 00:09:35 +0800 Subject: [PATCH 39/40] optimize swoole (#9261) --- frameworks/PHP/swoole/database.php | 2 +- frameworks/PHP/swoole/php.ini | 1 + frameworks/PHP/swoole/swoole-async-mysql.dockerfile | 1 + frameworks/PHP/swoole/swoole-async-postgres.dockerfile | 1 + frameworks/PHP/swoole/swoole-server.php | 6 ++---- frameworks/PHP/swoole/swoole-sync-mysql.dockerfile | 1 + frameworks/PHP/swoole/swoole-sync-postgres.dockerfile | 3 ++- 7 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frameworks/PHP/swoole/database.php b/frameworks/PHP/swoole/database.php index 19aac390968..97d3af6887a 100644 --- a/frameworks/PHP/swoole/database.php +++ b/frameworks/PHP/swoole/database.php @@ -144,7 +144,7 @@ public static function init(string $driver): void ->withUsername('benchmarkdbuser') ->withPassword('benchmarkdbpass'); - self::$pool = new PDOPool($config, 128); + self::$pool = new PDOPool($config, intval(1400 / swoole_cpu_num())); self::$driver = $driver; } diff --git a/frameworks/PHP/swoole/php.ini b/frameworks/PHP/swoole/php.ini index 082e86dedbc..089c4837bd5 100644 --- a/frameworks/PHP/swoole/php.ini +++ b/frameworks/PHP/swoole/php.ini @@ -1,3 +1,4 @@ +zend_extension=opcache.so opcache.enable=1 opcache.enable_cli=1 opcache.validate_timestamps=0 diff --git a/frameworks/PHP/swoole/swoole-async-mysql.dockerfile b/frameworks/PHP/swoole/swoole-async-mysql.dockerfile index 82dbe32833f..ebfe9084357 100644 --- a/frameworks/PHP/swoole/swoole-async-mysql.dockerfile +++ b/frameworks/PHP/swoole/swoole-async-mysql.dockerfile @@ -2,6 +2,7 @@ FROM ubuntu:24.04 ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 1 +ENV CPU_MULTIPLES 1 ENV DATABASE_DRIVER mysql ARG DEBIAN_FRONTEND=noninteractive diff --git a/frameworks/PHP/swoole/swoole-async-postgres.dockerfile b/frameworks/PHP/swoole/swoole-async-postgres.dockerfile index 4a6b27b2bb0..f8cd24cc887 100644 --- a/frameworks/PHP/swoole/swoole-async-postgres.dockerfile +++ b/frameworks/PHP/swoole/swoole-async-postgres.dockerfile @@ -2,6 +2,7 @@ FROM ubuntu:24.04 ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 1 +ENV CPU_MULTIPLES 1 ENV DATABASE_DRIVER pgsql ARG DEBIAN_FRONTEND=noninteractive diff --git a/frameworks/PHP/swoole/swoole-server.php b/frameworks/PHP/swoole/swoole-server.php index 3794c364cb7..13050d75ebb 100644 --- a/frameworks/PHP/swoole/swoole-server.php +++ b/frameworks/PHP/swoole/swoole-server.php @@ -8,9 +8,8 @@ $enableCoroutine = getenv('ENABLE_COROUTINE') == 1; $connection = $enableCoroutine ? Connections::class : Connection::class; -$server = new Server('0.0.0.0', 8080); $setting = [ - 'worker_num' => swoole_cpu_num() * 4, + 'worker_num' => swoole_cpu_num() * ((int) getenv('CPU_MULTIPLES')), 'log_file' => '/dev/null', 'enable_coroutine' => $enableCoroutine, 'enable_reuse_port' => true @@ -18,12 +17,11 @@ if ($enableCoroutine) { $setting['hook_flags'] = SWOOLE_HOOK_ALL; - $setting['worker_num'] = swoole_cpu_num(); } +$server = new Server('0.0.0.0', 8080); $server->set($setting); - $server->on('workerStart', function () use ($connection) { $connection::init(getenv('DATABASE_DRIVER')); }); diff --git a/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile b/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile index 97a0e11d111..6c1278bed67 100644 --- a/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile +++ b/frameworks/PHP/swoole/swoole-sync-mysql.dockerfile @@ -2,6 +2,7 @@ FROM ubuntu:24.04 ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 0 +ENV CPU_MULTIPLES 1 ENV DATABASE_DRIVER mysql ARG DEBIAN_FRONTEND=noninteractive diff --git a/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile b/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile index 1b5a68b6169..8651d205921 100644 --- a/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile +++ b/frameworks/PHP/swoole/swoole-sync-postgres.dockerfile @@ -2,6 +2,7 @@ FROM ubuntu:24.04 ENV SWOOLE_VERSION 5.1.4 ENV ENABLE_COROUTINE 0 +ENV CPU_MULTIPLES 4 ENV DATABASE_DRIVER pgsql ARG DEBIAN_FRONTEND=noninteractive @@ -15,7 +16,7 @@ RUN apt update -yqq > /dev/null \ && cd /tmp/swoole-src-${SWOOLE_VERSION} \ && phpize > /dev/null \ && ./configure > /dev/null \ - && make -j2 > /dev/null \ + && make -j8 > /dev/null \ && make install > /dev/null \ && echo "extension=swoole.so" > /etc/php/8.3/cli/conf.d/50-swoole.ini From 1d0f0af6294c9adc0f055bdef66a2c0c2f4b1a13 Mon Sep 17 00:00:00 2001 From: Denis Stepanov Date: Thu, 12 Sep 2024 18:10:36 +0200 Subject: [PATCH 40/40] Micronaut: Use JTE template engine and GraalVM 22 (#9262) * Micronaut: Use JTE template engine and GraalVM 22 * CR * User Graalvm 21 for Micronaut Data --- .../io.micronaut.benchmark.module.gradle | 2 +- frameworks/Java/micronaut/common/build.gradle | 24 +++++---- .../AbstractBenchmarkController.java | 15 ++++++ .../controller/AsyncBenchmarkController.java | 13 +---- .../controller/BenchmarkController.java | 17 ++---- .../controller/FortunesBodyWriter.java | 54 +++++++++++++++++++ .../ReactiveBenchmarkController.java | 15 +----- .../repository/FortuneRepository.java | 3 +- .../common/src/main/jte/fortunes.jte | 4 ++ .../main/resources/views/fortunes.rocker.html | 8 --- frameworks/Java/micronaut/gradle.properties | 2 +- .../java/benchmark/JdbcWorldRepository.java | 2 + .../micronaut/micronaut-graalvm.dockerfile | 2 +- .../micronaut-jdbc-graalvm.dockerfile | 2 +- .../java/benchmark/JdbcFortuneRepository.java | 2 +- .../micronaut-r2dbc-graalvm.dockerfile | 2 +- 16 files changed, 104 insertions(+), 63 deletions(-) create mode 100644 frameworks/Java/micronaut/common/src/main/java/benchmark/controller/FortunesBodyWriter.java create mode 100644 frameworks/Java/micronaut/common/src/main/jte/fortunes.jte delete mode 100644 frameworks/Java/micronaut/common/src/main/resources/views/fortunes.rocker.html diff --git a/frameworks/Java/micronaut/buildSrc/src/main/groovy/io.micronaut.benchmark.module.gradle b/frameworks/Java/micronaut/buildSrc/src/main/groovy/io.micronaut.benchmark.module.gradle index 43a854cf848..dcb6b3389fc 100644 --- a/frameworks/Java/micronaut/buildSrc/src/main/groovy/io.micronaut.benchmark.module.gradle +++ b/frameworks/Java/micronaut/buildSrc/src/main/groovy/io.micronaut.benchmark.module.gradle @@ -28,7 +28,7 @@ dependencies { } graalvmNative.binaries.all { - buildArgs.add("--initialize-at-build-time=views") + buildArgs.add("--initialize-at-build-time=gg.jte.generated.precompiled") } test { diff --git a/frameworks/Java/micronaut/common/build.gradle b/frameworks/Java/micronaut/common/build.gradle index c254fb8e743..8153fd5d8ea 100644 --- a/frameworks/Java/micronaut/common/build.gradle +++ b/frameworks/Java/micronaut/common/build.gradle @@ -1,7 +1,7 @@ plugins { id 'java' id "io.micronaut.library" - id "nu.studer.rocker" version "3.0.4" + id "gg.jte.gradle" version "3.1.12" } group 'io.micronaut.benchmark' @@ -16,14 +16,10 @@ micronaut { testRuntime "junit5" } -rocker { - configurations { - main { - templateDir = file('src/main/resources') - outputDir = file('build/generated/rocker') - optimize = true - } - } +jte { + sourceDirectory = file("src/main/jte").toPath() + generate() + binaryStaticContent = true } dependencies { @@ -38,7 +34,8 @@ dependencies { transitive = false } - implementation("com.fizzed:rocker-runtime") + // Switch to BOM version after https://github.com/micronaut-projects/micronaut-views/issues/876 + implementation("gg.jte:jte-runtime:3.1.12") runtimeOnly("ch.qos.logback:logback-classic") runtimeOnly("org.yaml:snakeyaml") @@ -46,4 +43,11 @@ dependencies { test { useJUnitPlatform() +} + +// Gradle requires that generateJte is run before some tasks +tasks.configureEach { + if (name == "inspectRuntimeClasspath") { + mustRunAfter("generateJte") + } } \ No newline at end of file diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AbstractBenchmarkController.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AbstractBenchmarkController.java index 637649b448e..8f595d99931 100644 --- a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AbstractBenchmarkController.java +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AbstractBenchmarkController.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; @@ -12,6 +13,20 @@ public class AbstractBenchmarkController { protected final Integer[] boxed = IntStream.range(1, 10001).boxed().toArray(Integer[]::new); + private static final Comparator FORTUNES_COMPARATOR = new Comparator<>() { + @Override + public int compare(Fortune o1, Fortune o2) { + return o1.message().compareTo(o2.message()); + } + }; + + protected List prepareFortunes(List fortuneList) { + List all = new ArrayList<>(fortuneList.size() + 1); + all.add(new Fortune(0, "Additional fortune added at request time.")); + all.addAll(fortuneList); + all.sort(FORTUNES_COMPARATOR); + return all; + } protected List createFortunes() { List fortuneMessages = IntStream.range(0, 10).boxed().toList(); diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AsyncBenchmarkController.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AsyncBenchmarkController.java index 7e40c36a204..a16ce1933c3 100644 --- a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AsyncBenchmarkController.java +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/AsyncBenchmarkController.java @@ -5,11 +5,9 @@ import benchmark.repository.AsyncFortuneRepository; import benchmark.repository.AsyncWorldRepository; import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpResponse; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.QueryValue; -import views.fortunes; import java.util.ArrayList; import java.util.Comparator; @@ -55,15 +53,8 @@ public CompletionStage> queries(@QueryValue String queries) { // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#fortunes @Get(value = "/fortunes", produces = "text/html;charset=utf-8") - public CompletionStage> fortune() { - return fortuneRepository.findAll().thenApply(fortuneList -> { - List all = new ArrayList<>(fortuneList.size() + 1); - all.add(new Fortune(0, "Additional fortune added at request time.")); - all.addAll(fortuneList); - all.sort(comparing(Fortune::message)); - String body = fortunes.template(all).render().toString(); - return HttpResponse.ok(body).contentType("text/html;charset=utf-8"); - }); + public CompletionStage> fortune() { + return fortuneRepository.findAll().thenApply(this::prepareFortunes); } // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/BenchmarkController.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/BenchmarkController.java index c00eed41fb4..f38940257d3 100644 --- a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/BenchmarkController.java +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/BenchmarkController.java @@ -5,19 +5,14 @@ import benchmark.repository.FortuneRepository; import benchmark.repository.WorldRepository; import io.micronaut.context.annotation.Requires; -import io.micronaut.http.HttpResponse; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.QueryValue; -import views.fortunes; import java.util.ArrayList; -import java.util.Collection; import java.util.Comparator; import java.util.List; -import static java.util.Comparator.comparing; - @Requires(beans = {WorldRepository.class, FortuneRepository.class}) @Controller public class BenchmarkController extends AbstractBenchmarkController { @@ -56,14 +51,8 @@ public List queries(@QueryValue String queries) { // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#fortunes @Get(value = "/fortunes", produces = "text/html;charset=utf-8") - public HttpResponse fortune() { - Collection all = fortuneRepository.findAll(); - List fortunesList = new ArrayList<>(all.size() + 1); - fortunesList.add(new Fortune(0, "Additional fortune added at request time.")); - fortunesList.addAll(all); - fortunesList.sort(comparing(Fortune::message)); - String body = fortunes.template(fortunesList).render().toString(); - return HttpResponse.ok(body).contentType("text/html;charset=utf-8"); + public List fortune() { + return prepareFortunes(fortuneRepository.findAll()); } // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates @@ -77,5 +66,5 @@ public List updates(@QueryValue String queries) { worldRepository.updateAll(worldList); return worldList; } - + } diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/FortunesBodyWriter.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/FortunesBodyWriter.java new file mode 100644 index 00000000000..a7bee37d493 --- /dev/null +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/FortunesBodyWriter.java @@ -0,0 +1,54 @@ +package benchmark.controller; + +import benchmark.model.Fortune; +import gg.jte.TemplateOutput; +import gg.jte.generated.precompiled.JtefortunesGenerated; +import gg.jte.html.OwaspHtmlTemplateOutput; +import io.micronaut.core.annotation.NonNull; +import io.micronaut.core.type.Argument; +import io.micronaut.core.type.MutableHeaders; +import io.micronaut.http.MediaType; +import io.micronaut.http.body.MessageBodyWriter; +import io.micronaut.http.codec.CodecException; +import io.micronaut.http.netty.NettyHttpHeaders; +import jakarta.inject.Singleton; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; + +@Singleton +public class FortunesBodyWriter implements MessageBodyWriter> { + + @Override + public void writeTo(@NonNull Argument> type, + @NonNull MediaType mediaType, + List values, + @NonNull MutableHeaders outgoingHeaders, + @NonNull OutputStream outputStream) throws CodecException { + outgoingHeaders.set(NettyHttpHeaders.CONTENT_TYPE, "text/html;charset=utf-8"); + TemplateOutput output = new TemplateOutput() { + + @Override + public void writeContent(String value) { + writeBinaryContent(value.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public void writeContent(String value, int beginIndex, int endIndex) { + writeBinaryContent(value.substring(beginIndex, endIndex).getBytes(StandardCharsets.UTF_8)); + } + + @Override + public void writeBinaryContent(byte[] value) { + try { + outputStream.write(value); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + JtefortunesGenerated.render(new OwaspHtmlTemplateOutput(output), null, values); + } +} diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/ReactiveBenchmarkController.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/ReactiveBenchmarkController.java index 8adbc4c4716..e85d236acee 100644 --- a/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/ReactiveBenchmarkController.java +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/controller/ReactiveBenchmarkController.java @@ -6,21 +6,17 @@ import benchmark.repository.ReactiveWorldRepository; import io.micronaut.context.annotation.Requires; import io.micronaut.core.async.annotation.SingleResult; -import io.micronaut.http.HttpResponse; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.http.annotation.QueryValue; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import views.fortunes; import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import static java.util.Comparator.comparing; - @Requires(beans = {ReactiveWorldRepository.class, ReactiveFortuneRepository.class}) @Controller public class ReactiveBenchmarkController extends AbstractBenchmarkController { @@ -61,15 +57,8 @@ public Publisher> queries(@QueryValue String queries) { // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#fortunes @Get(value = "/fortunes", produces = "text/html;charset=utf-8") @SingleResult - public Mono> fortune() { - return Mono.from(fortuneRepository.findAll()).map(fortuneList -> { - List all = new ArrayList<>(fortuneList.size() + 1); - all.add(new Fortune(0, "Additional fortune added at request time.")); - all.addAll(fortuneList); - all.sort(comparing(Fortune::message)); - String body = fortunes.template(all).render().toString(); - return HttpResponse.ok(body).contentType("text/html;charset=utf-8"); - }); + public Mono> fortune() { + return Mono.from(fortuneRepository.findAll()).map(this::prepareFortunes); } // https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#database-updates diff --git a/frameworks/Java/micronaut/common/src/main/java/benchmark/repository/FortuneRepository.java b/frameworks/Java/micronaut/common/src/main/java/benchmark/repository/FortuneRepository.java index 701f647e384..b1c8fe3989e 100644 --- a/frameworks/Java/micronaut/common/src/main/java/benchmark/repository/FortuneRepository.java +++ b/frameworks/Java/micronaut/common/src/main/java/benchmark/repository/FortuneRepository.java @@ -4,11 +4,12 @@ import org.reactivestreams.Publisher; import java.util.Collection; +import java.util.List; public interface FortuneRepository { void initDb(Collection fortunes); - Collection findAll(); + List findAll(); } diff --git a/frameworks/Java/micronaut/common/src/main/jte/fortunes.jte b/frameworks/Java/micronaut/common/src/main/jte/fortunes.jte new file mode 100644 index 00000000000..7ac61415c99 --- /dev/null +++ b/frameworks/Java/micronaut/common/src/main/jte/fortunes.jte @@ -0,0 +1,4 @@ +@param java.util.List fortunes +Fortunes@for(benchmark.model.Fortune fortune : fortunes) + @endfor +
idmessage
${fortune.id()}${fortune.message()}
\ No newline at end of file diff --git a/frameworks/Java/micronaut/common/src/main/resources/views/fortunes.rocker.html b/frameworks/Java/micronaut/common/src/main/resources/views/fortunes.rocker.html deleted file mode 100644 index c6b9d0124a6..00000000000 --- a/frameworks/Java/micronaut/common/src/main/resources/views/fortunes.rocker.html +++ /dev/null @@ -1,8 +0,0 @@ -@import java.util.* -@import benchmark.model.* -@args(List fortunes) -Fortunes - @for ((ForIterator i, Fortune fortune) : fortunes) { - - } -
idmessage
@fortune.id()@fortune.message()
\ No newline at end of file diff --git a/frameworks/Java/micronaut/gradle.properties b/frameworks/Java/micronaut/gradle.properties index 22d843f7643..8ce6479ffe6 100644 --- a/frameworks/Java/micronaut/gradle.properties +++ b/frameworks/Java/micronaut/gradle.properties @@ -1 +1 @@ -micronautVersion=4.6.0 +micronautVersion=4.6.1 diff --git a/frameworks/Java/micronaut/micronaut-data-jdbc/src/main/java/benchmark/JdbcWorldRepository.java b/frameworks/Java/micronaut/micronaut-data-jdbc/src/main/java/benchmark/JdbcWorldRepository.java index 3b08db89390..89e9a6be895 100644 --- a/frameworks/Java/micronaut/micronaut-data-jdbc/src/main/java/benchmark/JdbcWorldRepository.java +++ b/frameworks/Java/micronaut/micronaut-data-jdbc/src/main/java/benchmark/JdbcWorldRepository.java @@ -2,6 +2,7 @@ import benchmark.model.World; import benchmark.repository.WorldRepository; +import io.micronaut.data.connection.annotation.Connectable; import io.micronaut.data.jdbc.annotation.JdbcRepository; import io.micronaut.data.model.query.builder.sql.Dialect; import io.micronaut.data.repository.GenericRepository; @@ -20,6 +21,7 @@ default void initDb(Collection worlds) { void saveAll(Collection worlds); + @Connectable @Override default List findByIds(List ids) { return WorldRepository.super.findByIds(ids); diff --git a/frameworks/Java/micronaut/micronaut-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-graalvm.dockerfile index 0b45b87f1dc..c1e1207fa96 100644 --- a/frameworks/Java/micronaut/micronaut-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-graalvm.dockerfile @@ -1,4 +1,4 @@ -FROM container-registry.oracle.com/graalvm/native-image:21 +FROM container-registry.oracle.com/graalvm/native-image:22 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src diff --git a/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile index ceae0bdf03e..6b6e9262aa2 100644 --- a/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-jdbc-graalvm.dockerfile @@ -1,4 +1,4 @@ -FROM container-registry.oracle.com/graalvm/native-image:21 +FROM container-registry.oracle.com/graalvm/native-image:22 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src diff --git a/frameworks/Java/micronaut/micronaut-jdbc/src/main/java/benchmark/JdbcFortuneRepository.java b/frameworks/Java/micronaut/micronaut-jdbc/src/main/java/benchmark/JdbcFortuneRepository.java index 8b07fd1c6fc..2315804f7c2 100644 --- a/frameworks/Java/micronaut/micronaut-jdbc/src/main/java/benchmark/JdbcFortuneRepository.java +++ b/frameworks/Java/micronaut/micronaut-jdbc/src/main/java/benchmark/JdbcFortuneRepository.java @@ -42,7 +42,7 @@ public void initDb(Collection fortunes) { } @Override - public Collection findAll() { + public List findAll() { try (Connection connection = dataSource.getConnection()) { try (PreparedStatement statement = connection.prepareStatement("SELECT id, message FROM fortune", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { diff --git a/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile b/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile index 574496a0b91..06ccaea922c 100644 --- a/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile +++ b/frameworks/Java/micronaut/micronaut-r2dbc-graalvm.dockerfile @@ -1,4 +1,4 @@ -FROM container-registry.oracle.com/graalvm/native-image:21 +FROM container-registry.oracle.com/graalvm/native-image:22 RUN microdnf install findutils # Gradle 8.7 requires xargs COPY . /home/gradle/src WORKDIR /home/gradle/src