-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a3328f6
commit 047245a
Showing
13 changed files
with
465 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM microsoft/dotnet:2.1-sdk-stretch AS build | ||
WORKDIR /app | ||
COPY src/App . | ||
RUN dotnet publish -c Release -o out | ||
|
||
FROM microsoft/dotnet:2.1-aspnetcore-runtime AS runtime | ||
ENV ASPNETCORE_URLS http://+:8080 | ||
ENV COMPlus_ReadyToRun 0 | ||
WORKDIR /app | ||
COPY --from=build /app/out ./ | ||
|
||
ENTRYPOINT ["dotnet", "App.dll"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
module Custom | ||
|
||
open App | ||
open Dapper | ||
open Giraffe | ||
open System | ||
open Models | ||
open Npgsql | ||
open FSharp.Control.Tasks | ||
open System.IO | ||
|
||
let private DefaultCapacity = 1386 | ||
let private MaxBuilderSize = DefaultCapacity * 3 | ||
|
||
type MemoryStreamCache = | ||
|
||
[<ThreadStatic>] | ||
[<DefaultValue>] | ||
static val mutable private instance: MemoryStream | ||
|
||
static member Get() = MemoryStreamCache.Get(DefaultCapacity) | ||
static member Get(capacity:int) = | ||
|
||
if capacity <= MaxBuilderSize then | ||
let ms = MemoryStreamCache.instance; | ||
let capacity = max capacity DefaultCapacity | ||
|
||
if ms <> null && capacity <= ms.Capacity then | ||
MemoryStreamCache.instance <- null; | ||
ms.SetLength 0L | ||
ms | ||
else | ||
new MemoryStream(capacity) | ||
else | ||
new MemoryStream(capacity) | ||
|
||
static member Release(ms:MemoryStream) = | ||
if ms.Capacity <= MaxBuilderSize then | ||
MemoryStreamCache.instance <- ms | ||
|
||
let application : HttpHandler = | ||
|
||
let inline contentLength x = new Nullable<int64> ( int64 x ) | ||
|
||
let json' data : HttpHandler = | ||
let bytes = Utf8Json.JsonSerializer.Serialize(data) | ||
fun _ ctx -> | ||
ctx.Response.ContentLength <- contentLength bytes.Length | ||
ctx.Response.ContentType <- "application/json" | ||
ctx.Response.StatusCode <- 200 | ||
task { | ||
do! ctx.Response.Body.WriteAsync(bytes, 0, bytes.Length) | ||
return Some ctx | ||
} | ||
|
||
let text' (msg:string): HttpHandler = | ||
let bytes = System.Text.Encoding.UTF8.GetBytes(msg) | ||
fun _ ctx -> | ||
ctx.Response.ContentLength <- contentLength bytes.Length | ||
ctx.Response.ContentType <- "text/plain" | ||
ctx.Response.StatusCode <- 200 | ||
task { | ||
do! ctx.Response.Body.WriteAsync(bytes, 0, bytes.Length) | ||
return Some ctx | ||
} | ||
|
||
let fortunes' : HttpHandler = | ||
let extra = { id = 0; message = "Additional fortune added at request time." } | ||
fun _ ctx -> | ||
let conn = new NpgsqlConnection(ConnectionString) | ||
ctx.Response.RegisterForDispose conn | ||
task { | ||
let! data = conn.QueryAsync<Fortune>("SELECT id, message FROM fortune") | ||
|
||
let fortunes = | ||
let xs = data.AsList() | ||
xs.Add extra | ||
xs.Sort FortuneComparer | ||
xs | ||
|
||
let html = MemoryStreamCache.Get() | ||
let view = fortunes |> HtmlViews.fortunes | ||
StetefullRendering.renderHtmlToStream html view | ||
|
||
ctx.Response.ContentType <- "text/html;charset=utf-8" | ||
ctx.Response.ContentLength <- contentLength html.Length | ||
ctx.Response.StatusCode <- 200 | ||
do! html.CopyToAsync ctx.Response.Body | ||
|
||
MemoryStreamCache.Release html | ||
return Some ctx | ||
} | ||
|
||
let routes' (routes: (string * HttpHandler) list) : HttpHandler = | ||
let table = Map.ofList routes | ||
let notFound = setStatusCode 404 | ||
|
||
let go key = | ||
if table |> Map.containsKey key then | ||
table.[key] | ||
else | ||
notFound | ||
|
||
fun next ctx -> | ||
let path = ctx.Request.Path.Value | ||
let handler = go path | ||
handler next ctx | ||
|
||
routes' [ | ||
"/plaintext", text' "Hello, World!" | ||
"/json", json' { JsonStructMessage.message = "Hello, World!" } | ||
"/fortunes", fortunes' | ||
] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
module HtmlViews | ||
|
||
open Giraffe.GiraffeViewEngine | ||
open Models | ||
|
||
let private fortunesHead = | ||
head [] [ | ||
title [] [ rawText "Fortunes" ] | ||
] | ||
|
||
let private layout (content: XmlNode list) = | ||
html [] [ | ||
fortunesHead | ||
body [] content | ||
] | ||
|
||
let private fortunesTableHeader = | ||
tr [] [ | ||
th [] [ rawText "id" ] | ||
th [] [ rawText "message" ] | ||
] | ||
|
||
let fortunes (fortunes: Fortune seq) = | ||
[ | ||
table [] [ | ||
yield fortunesTableHeader | ||
for f in fortunes -> | ||
tr [] [ | ||
td [] [ rawText <| string f.id ] | ||
td [] [ encodedText <| f.message ] | ||
] | ||
] | ||
] |> layout |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module Models | ||
|
||
open System.Collections.Generic | ||
open System | ||
|
||
type JsonMessage = { message : string } | ||
|
||
[<Struct>] | ||
type JsonStructMessage = { message : string } | ||
|
||
[<CLIMutable>] | ||
type Fortune = { id: int; message: string } | ||
|
||
[<Literal>] | ||
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" | ||
|
||
type Implementation = Stock | Custom | ||
|
||
let FortuneComparer = { new IComparer<Fortune> with | ||
member self.Compare(a,b) = String.CompareOrdinal(a.message, b.message) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.