Skip to content

Commit

Permalink
Merge branch 'main' into feat/add-max-calculator-limiter
Browse files Browse the repository at this point in the history
  • Loading branch information
luk3skyw4lker authored Jul 22, 2024
2 parents 8cad8bf + ef07360 commit fd3ce6d
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 37 deletions.
81 changes: 70 additions & 11 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,21 @@ on:
paths-ignore:
- "**/*.md"

permissions:
# deployments permission to deploy GitHub pages website
deployments: write
# contents permission to update benchmark contents in gh-pages branch
contents: write

name: Benchmark
jobs:
Compare:
runs-on: ubuntu-latest
steps:
- name: Fetch Repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # to be able to retrieve the last commit in main

- name: Install Go
uses: actions/setup-go@v5
Expand All @@ -26,24 +34,75 @@ jobs:
- name: Run Benchmark
run: set -o pipefail; go test ./... -benchmem -run=^$ -bench . | tee output.txt

- name: Get Previous Benchmark Results
uses: actions/cache@v4
# NOTE: Benchmarks could change with different CPU types
- name: Get GitHub Runner System Information
uses: kenchan0130/[email protected]
id: system-info

- name: Get Main branch SHA
id: get-main-branch-sha
run: |
SHA=$(git rev-parse origin/main)
echo "sha=$SHA" >> $GITHUB_OUTPUT
- name: Get Benchmark Results from main branch
id: cache
uses: actions/cache/restore@v4
with:
path: ./cache
key: ${{ runner.os }}-benchmark
key: ${{ steps.get-main-branch-sha.outputs.sha }}-${{ runner.os }}-${{ steps.system-info.outputs.cpu-model }}-benchmark

- name: Save Benchmark Results
# This will only run if we have Benchmark Results from main branch
- name: Compare PR Benchmark Results with main branch
uses: benchmark-action/[email protected]
if: steps.cache.outputs.cache-hit == 'true'
with:
tool: "go"
tool: 'go'
output-file-path: output.txt
github-token: ${{ secrets.BENCHMARK_TOKEN }}
benchmark-data-dir-path: "benchmarks"
external-data-json-path: ./cache/benchmark-data.json
# Do not save the data (This allows comparing benchmarks)
save-data-file: false
fail-on-alert: true
comment-on-alert: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
# Enable Job Summary for PRs - deactivated because of issues
#summary-always: ${{ github.event_name != 'push' && github.event_name != 'workflow_dispatch' }}
comment-on-alert: true
github-token: ${{ secrets.GITHUB_TOKEN }}
summary-always: true
alert-threshold: "150%"

- name: Store Benchmark Results for main branch
uses: benchmark-action/[email protected]
if: ${{ github.ref_name == 'main' }}
with:
tool: 'go'
output-file-path: output.txt
external-data-json-path: ./cache/benchmark-data.json
# Save the data to external file (cache)
save-data-file: true
fail-on-alert: false
github-token: ${{ secrets.GITHUB_TOKEN }}
summary-always: true
alert-threshold: "150%"

- name: Publish Benchmark Results to GitHub Pages
uses: benchmark-action/[email protected]
if: ${{ github.ref_name == 'main' }}
with:
tool: 'go'
output-file-path: output.txt
benchmark-data-dir-path: "benchmarks"
fail-on-alert: false
github-token: ${{ secrets.GITHUB_TOKEN }}
comment-on-alert: true
summary-always: true
# Save the data to external file (GitHub Pages)
save-data-file: true
alert-threshold: "150%"
# TODO: reactivate it later -> when v3 is the stable one
#auto-push: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
auto-push: false
save-data-file: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}

- name: Update Benchmark Results cache
uses: actions/cache/save@v4
if: ${{ github.ref_name == 'main' }}
with:
path: ./cache
key: ${{ steps.get-main-branch-sha.outputs.sha }}-${{ runner.os }}-${{ steps.system-info.outputs.cpu-model }}-benchmark
46 changes: 46 additions & 0 deletions .github/workflows/manual-dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# https://github.com/dependabot/dependabot-script/blob/main/manual-github-actions.yaml
# https://github.com/dependabot/dependabot-script?tab=readme-ov-file#github-actions-standalone
name: ManualDependabot

on:
workflow_dispatch:
inputs:
package-manager:
description: 'The package manager to use'
required: true
default: 'gomod'
directory:
description: 'The directory to scan'
required: true
default: '/'

permissions:
contents: read

jobs:
dependabot:
permissions:
contents: write # for Git to git push
pull-requests: write # for repo-sync/pull-request to create pull requests
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v3

- name: Checkout dependabot
run: |
cd /tmp/
git clone https://github.com/dependabot/dependabot-script
- name: Build image
run: |
cd /tmp/dependabot-script
docker build -t "dependabot/dependabot-script" -f Dockerfile .
- name: Run dependabot
env:
PACKAGE_MANAGER: ${{ github.event.inputs.package-manager }}
DIRECTORY: ${{ github.event.inputs.directory }}
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
docker run -v $PWD:/src -e PROJECT_PATH=$GITHUB_REPOSITORY -e PACKAGE_MANAGER=$PACKAGE_MANAGER -e DIRECTORY=$DIRECTORY -e GITHUB_ACCESS_TOKEN=$GITHUB_ACCESS_TOKEN -e OPTIONS="$OPTIONS" dependabot/dependabot-script
28 changes: 18 additions & 10 deletions ctx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3099,23 +3099,25 @@ func Test_Ctx_SendFile_Compress_CheckCompressed(t *testing.T) {
expectedFileContent, err := io.ReadAll(f)
require.NoError(t, err)

sendFileBodyReader := func(compression string) []byte {
reqCtx := &fasthttp.RequestCtx{}
reqCtx.Request.Header.Add(HeaderAcceptEncoding, compression)
sendFileBodyReader := func(compression string) ([]byte, error) {
t.Helper()
c := app.AcquireCtx(&fasthttp.RequestCtx{})
defer app.ReleaseCtx(c)
c.Request().Header.Add(HeaderAcceptEncoding, compression)

c := app.AcquireCtx(reqCtx)
err = c.SendFile("./ctx.go", SendFile{
err := c.SendFile("./ctx.go", SendFile{
Compress: true,
})
require.NoError(t, err)

return c.Response().Body()
return c.Response().Body(), err
}

t.Run("gzip", func(t *testing.T) {
t.Parallel()

body, err := fasthttp.AppendGunzipBytes(nil, sendFileBodyReader("gzip"))
b, err := sendFileBodyReader("gzip")
require.NoError(t, err)
body, err := fasthttp.AppendGunzipBytes(nil, b)
require.NoError(t, err)

require.Equal(t, expectedFileContent, body)
Expand All @@ -3124,7 +3126,9 @@ func Test_Ctx_SendFile_Compress_CheckCompressed(t *testing.T) {
t.Run("zstd", func(t *testing.T) {
t.Parallel()

body, err := fasthttp.AppendUnzstdBytes(nil, sendFileBodyReader("zstd"))
b, err := sendFileBodyReader("zstd")
require.NoError(t, err)
body, err := fasthttp.AppendUnzstdBytes(nil, b)
require.NoError(t, err)

require.Equal(t, expectedFileContent, body)
Expand All @@ -3133,7 +3137,9 @@ func Test_Ctx_SendFile_Compress_CheckCompressed(t *testing.T) {
t.Run("br", func(t *testing.T) {
t.Parallel()

body, err := fasthttp.AppendUnbrotliBytes(nil, sendFileBodyReader("br"))
b, err := sendFileBodyReader("br")
require.NoError(t, err)
body, err := fasthttp.AppendUnbrotliBytes(nil, b)
require.NoError(t, err)

require.Equal(t, expectedFileContent, body)
Expand Down Expand Up @@ -3242,6 +3248,8 @@ func Test_Ctx_SendFile_Multiple(t *testing.T) {
require.Contains(t, string(body), tc.body)
}

app.sendfilesMutex.RLock()
defer app.sendfilesMutex.RUnlock()
require.Len(t, app.sendfiles, 3)
}

Expand Down
28 changes: 28 additions & 0 deletions docs/api/app.md
Original file line number Diff line number Diff line change
Expand Up @@ -573,3 +573,31 @@ Hooks is a method to return [hooks](./hooks.md) property.
```go title="Signature"
func (app *App) Hooks() *Hooks
```

## RebuildTree

The RebuildTree method is designed to rebuild the route tree and enable dynamic route registration. It returns a pointer to the App instance.

```go title="Signature"
func (app *App) RebuildTree() *App
```

**Note:** Use this method with caution. It is **not** thread-safe and calling it can be very performance-intensive, so it should be used sparingly and only in development mode. Avoid using it concurrently.

### Example Usage

Here’s an example of how to define and register routes dynamically:

```go
app.Get("/define", func(c Ctx) error { // Define a new route dynamically
app.Get("/dynamically-defined", func(c Ctx) error { // Adding a dynamically defined route
return c.SendStatus(http.StatusOK)
})

app.RebuildTree() // Rebuild the route tree to register the new route

return c.SendStatus(http.StatusOK)
})
```

In this example, a new route is defined and then `RebuildTree()` is called to make sure the new route is registered and available.
18 changes: 17 additions & 1 deletion docs/middleware/healthcheck.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ id: healthcheck

# Health Check

Liveness and readiness probes middleware for [Fiber](https://github.com/gofiber/fiber) that provides two endpoints for checking the liveness and readiness state of HTTP applications.
Liveness, readiness and startup probes middleware for [Fiber](https://github.com/gofiber/fiber) that provides three endpoints for checking the liveness, readiness, and startup state of HTTP applications.

## Overview

Expand All @@ -16,6 +16,10 @@ Liveness and readiness probes middleware for [Fiber](https://github.com/gofiber/
- **Default Endpoint**: `/readyz`
- **Behavior**: By default returns `true` immediately when the server is operational.

- **Startup Probe**: Checks if the application has completed its startup sequence and is ready to proceed with initialization and readiness checks.
- **Default Endpoint**: `/startupz`
- **Behavior**: By default returns `true` immediately when the server is operational.

- **HTTP Status Codes**:
- `200 OK`: Returned when the checker function evaluates to `true`.
- `503 Service Unavailable`: Returned when the checker function evaluates to `false`.
Expand Down Expand Up @@ -44,6 +48,8 @@ After you initiate your [Fiber](https://github.com/gofiber/fiber) app, you can u
app.Get(healthcheck.DefaultLivenessEndpoint, healthcheck.NewHealthChecker())
// Provide a minimal config for readiness check
app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker())
// Provide a minimal config for startup check
app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker())
// Provide a minimal config for check with custom endpoint
app.Get("/live", healthcheck.NewHealthChecker())

Expand All @@ -59,6 +65,12 @@ app.Get(healthcheck.DefaultReadinessEndpoint, healthcheck.NewHealthChecker(healt
return true
},
}))
// And it works the same for startup, just change the route
app.Get(healthcheck.DefaultStartupEndpoint, healthcheck.NewHealthChecker(healthcheck.Config{
Probe: func(c fiber.Ctx) bool {
return true
},
}))
// With a custom route and custom probe
app.Get("/live", healthcheck.NewHealthChecker(healthcheck.Config{
Probe: func(c fiber.Ctx) bool {
Expand Down Expand Up @@ -90,6 +102,10 @@ type Config struct {
// Function used for checking the liveness of the application. Returns true if the application
// is running and false if it is not. The liveness probe is typically used to indicate if
// the application is in a state where it can handle requests (e.g., the server is up and running).
// The readiness probe is typically used to indicate if the application is ready to start accepting traffic (e.g., all necessary components
// are initialized and dependent services are available) and the startup probe typically used to
// indicate if the application has completed its startup sequence and is ready to proceed with
// initialization and readiness checks
//
// Optional. Default: func(c fiber.Ctx) bool { return true }
Probe HealthChecker
Expand Down
Loading

0 comments on commit fd3ce6d

Please sign in to comment.