├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug-report.yaml │ ├── feature-request.yaml │ └── question.yaml ├── dependabot.yml ├── labeler.yml ├── logo-dark.svg ├── logo.svg ├── release-drafter-template.yml ├── release.yml ├── scripts │ ├── initialize-wrangler.sh │ ├── sync_docs.sh │ └── update-deps.sh └── workflows │ ├── auto-labeler.yml │ ├── benchmark.yml │ ├── dependabot_automerge.yml │ ├── golangci-lint.yml │ ├── release-drafter.yml │ ├── sync-docs.yml │ ├── test-aerospike.yml │ ├── test-arangodb.yml │ ├── test-azureblob.yml │ ├── test-badger.yml │ ├── test-bbolt.yml │ ├── test-cassandra.yml │ ├── test-clickhouse.yml │ ├── test-cloudflarekv.yml │ ├── test-coherence.yml │ ├── test-couchbase.yml │ ├── test-dynamodb.yml │ ├── test-etcd.yml │ ├── test-leveldb.yml │ ├── test-memcache.yml │ ├── test-memory.yml │ ├── test-minio.yml │ ├── test-mockstorage.yml │ ├── test-mongodb.yml │ ├── test-mssql.yml │ ├── test-mysql.yml │ ├── test-nats.yml │ ├── test-neo4j.yml │ ├── test-pebble.yml │ ├── test-postgres.yml │ ├── test-redis.yml │ ├── test-ristretto.yml │ ├── test-rueidis.yml │ ├── test-s3.yml │ ├── test-scylladb.yml │ ├── test-sqlite3.yml │ ├── test-surrealdb.yml │ ├── test-teshelpers-redis.yml │ └── test-valkey.yml ├── .gitignore ├── LICENSE ├── MIGRATE.md ├── README.md ├── aerospike ├── README.md ├── aerospike.go ├── aerospike_test.go ├── config.go ├── go.mod └── go.sum ├── arangodb ├── README.md ├── arangodb.go ├── arangodb_test.go ├── config.go ├── go.mod └── go.sum ├── azureblob ├── README.md ├── azureblob.go ├── azureblob_test.go ├── config.go ├── go.mod └── go.sum ├── badger ├── .gitignore ├── README.md ├── badger.go ├── badger_test.go ├── config.go ├── config_test.go ├── go.mod └── go.sum ├── bbolt ├── README.md ├── bbolt.go ├── bbolt_test.go ├── config.go ├── go.mod ├── go.sum └── utils.go ├── cassandra ├── README.md ├── cassandra.go ├── cassandra_test.go ├── config.go ├── go.mod └── go.sum ├── clickhouse ├── README.md ├── clickhouse.go ├── clickhouse_test.go ├── config.go ├── go.mod └── go.sum ├── cloudflarekv ├── .gitignore ├── README.md ├── cloudflarekv.go ├── cloudflarekv_test.go ├── config.go ├── go.mod ├── go.sum └── test_module.go ├── coherence ├── README.md ├── coherence.go ├── coherence_test.go ├── go.mod └── go.sum ├── couchbase ├── README.md ├── config.go ├── couchbase.go ├── couchbase_test.go ├── go.mod └── go.sum ├── dynamodb ├── README.md ├── config.go ├── dynamodb.go ├── dynamodb_test.go ├── go.mod └── go.sum ├── etcd ├── README.md ├── config.go ├── etcd.go ├── etcd_test.go ├── go.mod └── go.sum ├── go.mod ├── go.sum ├── go.work ├── leveldb ├── README.md ├── config.go ├── config_test.go ├── go.mod ├── go.sum ├── leveldb.go └── leveldb_test.go ├── memcache ├── README.md ├── config.go ├── go.mod ├── go.sum ├── memcache.go └── memcache_test.go ├── memory ├── README.md ├── config.go ├── go.mod ├── go.sum ├── internal │ ├── time.go │ └── time_test.go ├── memory.go └── memory_test.go ├── minio ├── README.md ├── config.go ├── go.mod ├── go.sum ├── minio.go └── minio_test.go ├── mockstorage ├── README.md ├── go.mod ├── go.sum ├── mockstorage.go └── mockstorage_test.go ├── mongodb ├── README.md ├── config.go ├── go.mod ├── go.sum ├── mongodb.go └── mongodb_test.go ├── mssql ├── README.md ├── config.go ├── go.mod ├── go.sum ├── mssql.go └── mssql_test.go ├── mysql ├── README.md ├── config.go ├── go.mod ├── go.sum ├── mysql.go └── mysql_test.go ├── nats ├── README.md ├── config.go ├── go.mod ├── go.sum ├── nats.go ├── nats_test.go └── testdata │ └── nats-tls.conf ├── neo4j ├── README.md ├── config.go ├── go.mod ├── go.sum ├── neo4j.go └── neo4j_test.go ├── pebble ├── README.md ├── config.go ├── go.mod ├── go.sum ├── pebble.go └── pebble_test.go ├── postgres ├── README.md ├── config.go ├── go.mod ├── go.sum ├── postgres.go └── postgres_test.go ├── redis ├── README.md ├── config.go ├── go.mod ├── go.sum ├── redis.go └── redis_test.go ├── ristretto ├── README.md ├── config.go ├── go.mod ├── go.sum ├── ristretto.go └── ristretto_test.go ├── rueidis ├── README.md ├── config.go ├── go.mod ├── go.sum ├── rueidis.go └── rueidis_test.go ├── s3 ├── README.md ├── config.go ├── go.mod ├── go.sum ├── init_test.go ├── s3.go ├── s3_methods.go ├── s3_methods_test.go └── s3_test.go ├── scylladb ├── README.md ├── config.go ├── go.mod ├── go.sum ├── scylladb.go └── scylladb_test.go ├── sqlite3 ├── README.md ├── config.go ├── go.mod ├── go.sum ├── sqlite3.go └── sqlite3_test.go ├── storage.go ├── surrealdb ├── README.md ├── config.go ├── go.mod ├── go.sum ├── surrealdb.go └── surrealdb_test.go ├── testhelpers └── redis │ ├── go.mod │ ├── go.sum │ ├── redis.go │ └── redis_test.go └── valkey ├── README.md ├── config.go ├── go.mod ├── go.sum ├── valkey.go └── valkey_test.go /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @gofiber/maintainers -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yaml: -------------------------------------------------------------------------------- 1 | name: "\U0001F41B Bug Report" 2 | title: "\U0001F41B [Bug]: " 3 | description: Create a bug report to help us fix it. 4 | labels: ["☢️ Bug"] 5 | 6 | body: 7 | - type: markdown 8 | id: notice 9 | attributes: 10 | value: | 11 | ### Notice 12 | - Dont't forget you can ask your questions on our [Discord server](https://gofiber.io/discord). 13 | - If you think Fiber storage don't have a nice feature that you think, open the issue with **✏️ Feature Request** template. 14 | - Write your issue with clear and understandable English. 15 | - type: textarea 16 | id: description 17 | attributes: 18 | label: "Bug Description" 19 | description: "A clear and detailed description of what the bug is." 20 | placeholder: "Explain your problem as clear and detailed." 21 | validations: 22 | required: true 23 | - type: textarea 24 | id: how-to-reproduce 25 | attributes: 26 | label: How to Reproduce 27 | description: "Steps to reproduce the behavior and what should be observed in the end." 28 | placeholder: "Tell us step by step how we can replicate your problem and what we should see in the end." 29 | value: | 30 | Steps to reproduce the behavior: 31 | 1. Go to '....' 32 | 2. Click on '....' 33 | 3. Do '....' 34 | 4. See '....' 35 | validations: 36 | required: true 37 | - type: textarea 38 | id: expected-behavior 39 | attributes: 40 | label: Expected Behavior 41 | description: "A clear and detailed description of what you think should happens." 42 | placeholder: "Tell us what storage should normally do." 43 | validations: 44 | required: true 45 | - type: input 46 | id: version 47 | attributes: 48 | label: "Storage package Version" 49 | description: "Some bugs may be fixed in future storage releases, so we have to know your storage package version." 50 | placeholder: "Write your storage version. (v1.0.0, v1.1.0...)" 51 | validations: 52 | required: true 53 | - type: textarea 54 | id: snippet 55 | attributes: 56 | label: "Code Snippet (optional)" 57 | description: "For some issues, we need to know some parts of your code." 58 | placeholder: "Share a code you think related to the issue." 59 | render: go 60 | value: | 61 | package main 62 | 63 | import "github.com/gofiber/storage/%package%" 64 | 65 | func main() { 66 | // Steps to reproduce 67 | } 68 | - type: checkboxes 69 | id: terms 70 | attributes: 71 | label: "Checklist:" 72 | description: "By submitting this issue, you confirm that:" 73 | options: 74 | - label: "I agree to follow Fiber's [Code of Conduct](https://github.com/gofiber/fiber/blob/master/.github/CODE_OF_CONDUCT.md)." 75 | required: true 76 | - label: "I have checked for existing issues that describe my problem prior to opening this one." 77 | required: true 78 | - label: "I understand that improperly formatted bug reports may be closed without explanation." 79 | required: true 80 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yaml: -------------------------------------------------------------------------------- 1 | name: "\U0001F680 Feature Request" 2 | title: "\U0001F680 [Feature]: " 3 | description: Suggest an idea to improve this project. 4 | labels: ["✏️ Feature"] 5 | 6 | body: 7 | - type: markdown 8 | id: notice 9 | attributes: 10 | value: | 11 | ### Notice 12 | - Dont't forget you can ask your questions on our [Discord server](https://gofiber.io/discord). 13 | - If you think this is just a bug, open the issue with **☢️ Bug Report** template. 14 | - Write your issue with clear and understandable English. 15 | - type: textarea 16 | id: description 17 | attributes: 18 | label: "Feature Description" 19 | description: "A clear and detailed description of the feature we need to do." 20 | placeholder: "Explain your feature as clear and detailed." 21 | validations: 22 | required: true 23 | - type: textarea 24 | id: additional-context 25 | attributes: 26 | label: "Additional Context (optional)" 27 | description: "If you have something else to describe, write them here." 28 | placeholder: "Write here what you can describe differently." 29 | - type: textarea 30 | id: snippet 31 | attributes: 32 | label: "Code Snippet (optional)" 33 | description: "Code snippet may be really helpful to describe some features." 34 | placeholder: "Share a code to explain the feature better." 35 | render: go 36 | value: | 37 | package main 38 | 39 | import "github.com/gofiber/storage/%package%" 40 | 41 | func main() { 42 | // Steps to reproduce 43 | } 44 | - type: checkboxes 45 | id: terms 46 | attributes: 47 | label: "Checklist:" 48 | description: "By submitting this issue, you confirm that:" 49 | options: 50 | - label: "I agree to follow Fiber's [Code of Conduct](https://github.com/gofiber/fiber/blob/master/.github/CODE_OF_CONDUCT.md)." 51 | required: true 52 | - label: "I have checked for existing issues that describe my suggestion prior to opening this one." 53 | required: true 54 | - label: "I understand that improperly formatted feature requests may be closed without explanation." 55 | required: true 56 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yaml: -------------------------------------------------------------------------------- 1 | name: "🤔 Question" 2 | title: "\U0001F917 [Question]: " 3 | description: Ask a question so we can help you easily. 4 | labels: ["🤔 Question"] 5 | 6 | body: 7 | - type: markdown 8 | id: notice 9 | attributes: 10 | value: | 11 | ### Notice 12 | - Dont't forget you can ask your questions on our [Discord server](https://gofiber.io/discord). 13 | - If you think this is just a bug, open the issue with **☢️ Bug Report** template. 14 | - If you think Fiber storage don't have a nice feature that you think, open the issue with **✏️ Feature Request** template. 15 | - Write your issue with clear and understandable English. 16 | - type: textarea 17 | id: description 18 | attributes: 19 | label: "Question Description" 20 | description: "A clear and detailed description of the question." 21 | placeholder: "Explain your question as clear and detailed." 22 | validations: 23 | required: true 24 | - type: textarea 25 | id: snippet 26 | attributes: 27 | label: "Code Snippet (optional)" 28 | description: "Code snippet may be really helpful to describe some features." 29 | placeholder: "Share a code to explain the feature better." 30 | render: go 31 | value: | 32 | package main 33 | 34 | import "github.com/gofiber/storage/%package%" 35 | 36 | func main() { 37 | // Steps to reproduce 38 | } 39 | - type: checkboxes 40 | id: terms 41 | attributes: 42 | label: "Checklist:" 43 | description: "By submitting this issue, you confirm that:" 44 | options: 45 | - label: "I agree to follow Fiber's [Code of Conduct](https://github.com/gofiber/fiber/blob/master/.github/CODE_OF_CONDUCT.md)." 46 | required: true 47 | - label: "I have checked for existing issues that describe my questions prior to opening this one." 48 | required: true 49 | - label: "I understand that improperly formatted questions may be closed without explanation." 50 | required: true 51 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 2 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#directories 3 | 4 | version: 2 5 | updates: 6 | - package-ecosystem: "github-actions" 7 | open-pull-requests-limit: 15 8 | directory: "/" 9 | labels: 10 | - "🤖 Dependencies" 11 | schedule: 12 | interval: "daily" 13 | - package-ecosystem: "gomod" 14 | open-pull-requests-limit: 15 15 | directories: 16 | - "**/*" 17 | labels: 18 | - "🤖 Dependencies" 19 | schedule: 20 | interval: "daily" 21 | groups: 22 | testcontainers-modules: 23 | patterns: 24 | - "github.com/testcontainers/testcontainers-go" 25 | - "github.com/testcontainers/testcontainers-go/modules/**" 26 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | version: v1 2 | labels: 3 | - label: '📒 Documentation' 4 | matcher: 5 | title: '\b(docs|doc:|\[doc\]|README|typos|comment|documentation)\b' 6 | - label: '☢️ Bug' 7 | matcher: 8 | title: '\b(fix|race|bug|missing|correct)\b' 9 | - label: '🧹 Updates' 10 | matcher: 11 | title: '\b(improve|update|refactor|deprecated|remove|unused|test)\b' 12 | - label: '🤖 Dependencies' 13 | matcher: 14 | title: '\b(bumb|bdependencies)\b' 15 | - label: '✏️ Feature' 16 | matcher: 17 | title: '\b(feature|create|implement|add)\b' 18 | - label: '🤔 Question' 19 | matcher: 20 | title: '\b(question|how)\b' 21 | -------------------------------------------------------------------------------- /.github/release-drafter-template.yml: -------------------------------------------------------------------------------- 1 | name-template: '{{FOLDER}} - v$RESOLVED_VERSION' 2 | tag-template: '{{FOLDER}}/v$RESOLVED_VERSION' 3 | tag-prefix: {{FOLDER}}/v 4 | include-paths: 5 | - {{FOLDER}} 6 | categories: 7 | - title: '❗ Breaking Changes' 8 | labels: 9 | - '❗ BreakingChange' 10 | - title: '🚀 New' 11 | labels: 12 | - '✏️ Feature' 13 | - title: '🧹 Updates' 14 | labels: 15 | - '🧹 Updates' 16 | - '🤖 Dependencies' 17 | - title: '🐛 Fixes' 18 | labels: 19 | - '☢️ Bug' 20 | - title: '📚 Documentation' 21 | labels: 22 | - '📒 Documentation' 23 | change-template: '- $TITLE (#$NUMBER)' 24 | change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. 25 | exclude-contributors: 26 | - dependabot 27 | - dependabot[bot] 28 | version-resolver: 29 | major: 30 | labels: 31 | - 'major' 32 | - '❗ BreakingChange' 33 | minor: 34 | labels: 35 | - 'minor' 36 | - '✏️ Feature' 37 | patch: 38 | labels: 39 | - 'patch' 40 | - '📒 Documentation' 41 | - '☢️ Bug' 42 | - '🤖 Dependencies' 43 | - '🧹 Updates' 44 | default: patch 45 | template: | 46 | $CHANGES 47 | 48 | **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...{{FOLDER}}/v$RESOLVED_VERSION 49 | 50 | Thank you $CONTRIBUTORS for making this update possible. 51 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | # .github/release.yml 2 | 3 | changelog: 4 | categories: 5 | - title: '❗ Breaking Changes' 6 | labels: 7 | - '❗ BreakingChange' 8 | - title: '🚀 New Features' 9 | labels: 10 | - '✏️ Feature' 11 | - '📝 Proposal' 12 | - title: '🧹 Updates' 13 | labels: 14 | - '🧹 Updates' 15 | - '⚡️ Performance' 16 | - title: '🐛 Bug Fixes' 17 | labels: 18 | - '☢️ Bug' 19 | - title: '🛠️ Maintenance' 20 | labels: 21 | - '🤖 Dependencies' 22 | - title: '📚 Documentation' 23 | labels: 24 | - '📒 Documentation' 25 | - title: 'Other Changes' 26 | labels: 27 | - '*' 28 | -------------------------------------------------------------------------------- /.github/scripts/initialize-wrangler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # generate cloudflarekv/index.ts 4 | cat < cloudflarekv/index.ts 5 | export default { async fetch(Request, env) { 6 | 7 | const namespace = env.TEST_NAMESPACE1; 8 | 9 | if (Request.url === "http://localhost:8787/health") { 10 | return new Response("Success"); 11 | } 12 | 13 | if (Request.url === "http://localhost:8787/writeworkerskvkeyvaluepair") { 14 | const res = await Request.json(); 15 | const { key, val } = res; 16 | WriteWorkersKVKeyValuePair(namespace, key, val); 17 | return new Response("Success"); 18 | } 19 | 20 | else if (Request.url === "http://localhost:8787/listworkerskvkeys") { 21 | const resp = await Request.json(); 22 | const { limit, prefix, cursor } = resp; 23 | const list = await ListWorkersKVKeys(namespace, limit, prefix, cursor); 24 | return new Response(list); 25 | } 26 | 27 | else if (Request.url === "http://localhost:8787/deleteworkerskvpairbykey") { 28 | const res = await Request.json(); 29 | const { key } = res; 30 | await DeleteWorkersKVPairByKey(namespace, key); 31 | 32 | return new Response(key) 33 | } 34 | 35 | else if (Request.url === "http://localhost:8787/getworkerskvvaluebykey") { 36 | const key = (await Request.json()).key; 37 | const res = await GetWorkersKVValueByKey(namespace, key); 38 | 39 | return new Response(res); 40 | } 41 | 42 | else if (Request.url === "http://localhost:8787/deleteworkerskventries") { 43 | const res = await Request.json(); 44 | const { keys } = res; 45 | const newKeys = keys.filter(x => x.length > 0); 46 | await DeleteWorkersKVEntries(namespace, newKeys); 47 | 48 | return new Response("Success") 49 | } 50 | } 51 | } 52 | 53 | const GetWorkersKVValueByKey = async (NAMESPACE, key) => { 54 | const val = await NAMESPACE.get(key); 55 | 56 | return val; 57 | } 58 | 59 | const WriteWorkersKVKeyValuePair = async (NAMESPACE, key, val) => { 60 | await NAMESPACE.put(key, val); 61 | 62 | return "Wrote Successfully" 63 | } 64 | 65 | const DeleteWorkersKVPairByKey = async (NAMESPACE, key) => { 66 | await NAMESPACE.delete(key); 67 | 68 | return "Delete Successfully" 69 | } 70 | 71 | const ListWorkersKVKeys = async (NAMESPACE, limit, prefix, cursor) => { 72 | const resp = await NAMESPACE.list({ limit, prefix, cursor }); 73 | 74 | return JSON.stringify(resp.keys); 75 | } 76 | 77 | const DeleteWorkersKVEntries = async (NAMESPACE, keys) => { 78 | for (let key of keys) { 79 | await NAMESPACE.delete(key); 80 | } 81 | 82 | return "Delete Successfully" 83 | } 84 | 85 | 86 | EOF 87 | 88 | echo "index.ts generated" 89 | 90 | # generate cloudflarekv/wrangler.toml 91 | cat < cloudflarekv/wrangler.toml 92 | main = "index.ts" 93 | 94 | kv_namespaces = [ 95 | { binding = "TEST_NAMESPACE1", id = "hello", preview_id = "world" }, 96 | ] 97 | 98 | workers_dev = true 99 | 100 | compatibility_date = "2024-03-20" 101 | 102 | [dev] 103 | port = 8787 104 | local_protocol = "http" 105 | EOF 106 | 107 | echo "wrangler.toml generated" 108 | -------------------------------------------------------------------------------- /.github/scripts/sync_docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # Some env variables 5 | BRANCH="main" 6 | REPO_URL="github.com/gofiber/docs.git" 7 | AUTHOR_EMAIL="github-actions[bot]@users.noreply.github.com" 8 | AUTHOR_USERNAME="github-actions[bot]" 9 | VERSION_FILE="storage_versions.json" 10 | REPO_DIR="storage" 11 | COMMIT_URL="https://github.com/gofiber/storage" 12 | DOCUSAURUS_COMMAND="npm run docusaurus -- docs:version:storage" 13 | 14 | # Set commit author 15 | git config --global user.email "${AUTHOR_EMAIL}" 16 | git config --global user.name "${AUTHOR_USERNAME}" 17 | 18 | git clone https://${TOKEN}@${REPO_URL} fiber-docs 19 | 20 | # Handle push event 21 | if [ "$EVENT" == "push" ]; then 22 | latest_commit=$(git rev-parse --short HEAD) 23 | 24 | for f in $(find . -type f -name "*.md" -not -path "./fiber-docs/*"); do 25 | log_output=$(git log --oneline "${BRANCH}" HEAD~1..HEAD --name-status -- "${f}") 26 | 27 | if [[ $log_output != "" || ! -f "fiber-docs/docs/${REPO_DIR}/$f" ]]; then 28 | mkdir -p fiber-docs/docs/${REPO_DIR}/$(dirname $f) 29 | cp "${f}" fiber-docs/docs/${REPO_DIR}/$f 30 | fi 31 | done 32 | 33 | # Handle release event 34 | elif [ "$EVENT" == "release" ]; then 35 | # Extract package name from tag 36 | package_name="${TAG_NAME%/*}" 37 | major_version="${TAG_NAME#*/}" 38 | major_version="${major_version%%.*}" 39 | 40 | # Form new version name 41 | new_version="${package_name}_${major_version}.x.x" 42 | 43 | cd fiber-docs/ || true 44 | npm ci 45 | 46 | # Check if contrib_versions.json exists and modify it if required 47 | if [[ -f $VERSION_FILE ]]; then 48 | jq --arg new_version "$new_version" 'del(.[] | select(. == $new_version))' $VERSION_FILE > temp.json && mv temp.json $VERSION_FILE 49 | fi 50 | 51 | # Run docusaurus versioning command 52 | $DOCUSAURUS_COMMAND "${new_version}" 53 | 54 | if [[ -f $VERSION_FILE ]]; then 55 | jq 'sort | reverse' ${VERSION_FILE} > temp.json && mv temp.json ${VERSION_FILE} 56 | fi 57 | fi 58 | 59 | # Push changes 60 | cd fiber-docs/ || true 61 | git add . 62 | if [[ $EVENT == "push" ]]; then 63 | git commit -m "Add docs from ${COMMIT_URL}/commit/${latest_commit}" 64 | elif [[ $EVENT == "release" ]]; then 65 | git commit -m "Sync docs for release ${COMMIT_URL}/releases/tag/${TAG_NAME}" 66 | fi 67 | 68 | MAX_RETRIES=5 69 | DELAY=5 70 | retry=0 71 | 72 | while ((retry < MAX_RETRIES)) 73 | do 74 | git push https://${TOKEN}@${REPO_URL} && break 75 | retry=$((retry + 1)) 76 | git pull --rebase 77 | sleep $DELAY 78 | done 79 | 80 | if ((retry == MAX_RETRIES)) 81 | then 82 | echo "Failed to push after $MAX_RETRIES attempts. Exiting with 1." 83 | exit 1 84 | fi 85 | -------------------------------------------------------------------------------- /.github/scripts/update-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Loop over all directories except dot-directories 4 | for dir in */ ; do 5 | # Skip hidden directories 6 | [[ "$dir" == .* ]] && continue 7 | 8 | if [ -d "$dir" ]; then 9 | echo "Processing $dir" 10 | ( 11 | cd "$dir" || exit 12 | 13 | if [ -f "go.mod" ]; then 14 | goversion=$(grep '^go ' go.mod | awk '{print $2}') 15 | if [ -n "$goversion" ]; then 16 | major=$(echo "$goversion" | cut -d. -f1) 17 | minor=$(echo "$goversion" | cut -d. -f2) 18 | 19 | # If Go version is >= 1.23 20 | if [ "$major" -gt 1 ] || { [ "$major" -eq 1 ] && [ "$minor" -ge 23 ]; }; then 21 | echo "Running go get -u (go.mod version: $goversion)" 22 | GOTOOLCHAIN=local go get -u 23 | else 24 | echo "Skipping go get -u (go.mod version: $goversion < 1.23)" 25 | fi 26 | fi 27 | fi 28 | 29 | GOTOOLCHAIN=local go mod tidy 30 | ) 31 | fi 32 | done 33 | 34 | -------------------------------------------------------------------------------- /.github/workflows/auto-labeler.yml: -------------------------------------------------------------------------------- 1 | name: Auto labeler 2 | on: 3 | issues: 4 | types: [ opened, edited, milestoned ] 5 | pull_request_target: 6 | types: [ opened ] 7 | permissions: 8 | contents: read 9 | issues: write 10 | pull-requests: write 11 | statuses: write 12 | checks: write 13 | jobs: 14 | labeler: 15 | runs-on: ubuntu-latest 16 | if: ${{ github.actor != 'dependabot[bot]' }} 17 | steps: 18 | - name: Check Labels 19 | id: labeler 20 | uses: fuxingloh/multi-labeler@v4 21 | with: 22 | github-token: ${{secrets.GITHUB_TOKEN}} 23 | -------------------------------------------------------------------------------- /.github/workflows/dependabot_automerge.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot auto-merge 2 | on: 3 | pull_request 4 | 5 | permissions: 6 | contents: write 7 | pull-requests: write 8 | 9 | jobs: 10 | wait_for_checks: 11 | runs-on: ubuntu-latest 12 | if: ${{ github.actor == 'dependabot[bot]' }} 13 | steps: 14 | - name: Wait for check is finished 15 | uses: lewagon/wait-on-check-action@v1.3.4 16 | id: wait_for_checks 17 | with: 18 | ref: ${{ github.event.pull_request.head.sha || github.sha }} 19 | running-workflow-name: wait_for_checks 20 | check-regexp: Tests 21 | repo-token: ${{ secrets.PR_TOKEN }} 22 | wait-interval: 10 23 | dependabot: 24 | needs: [wait_for_checks] 25 | name: Dependabot auto-merge 26 | runs-on: ubuntu-latest 27 | if: ${{ github.actor == 'dependabot[bot]' }} 28 | steps: 29 | - name: Dependabot metadata 30 | id: metadata 31 | uses: dependabot/fetch-metadata@v2.4.0 32 | with: 33 | github-token: "${{ secrets.PR_TOKEN }}" 34 | - name: Enable auto-merge for Dependabot PRs 35 | if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor' || steps.metadata.outputs.update-type == 'version-update:semver-patch'}} 36 | run: | 37 | gh pr review --approve "$PR_URL" 38 | gh pr merge --auto --merge "$PR_URL" 39 | env: 40 | PR_URL: ${{github.event.pull_request.html_url}} 41 | GITHUB_TOKEN: ${{secrets.PR_TOKEN}} 42 | -------------------------------------------------------------------------------- /.github/workflows/golangci-lint.yml: -------------------------------------------------------------------------------- 1 | name: Golangci-Lint Check 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | - "main" 8 | paths-ignore: 9 | - "**.md" 10 | - LICENSE 11 | - ".github/ISSUE_TEMPLATE/*.yml" 12 | - ".github/dependabot.yml" 13 | pull_request: 14 | branches: 15 | - "*" 16 | paths-ignore: 17 | - "**.md" 18 | - LICENSE 19 | - ".github/ISSUE_TEMPLATE/*.yml" 20 | - ".github/dependabot.yml" 21 | 22 | jobs: 23 | changes: 24 | runs-on: ubuntu-latest 25 | steps: 26 | - name: Fetch Repository 27 | uses: actions/checkout@v4 28 | with: 29 | fetch-depth: 0 30 | 31 | - name: Generate filters 32 | id: filter-setup 33 | run: | 34 | filters=$(find . -maxdepth 1 -type d ! -path ./.git ! -path . ! -path ./testhelpers -exec basename {} \; | grep -v '^\.' | awk '{printf "%s: \"%s/**\"\n", $1, $1}') 35 | # Add all testhelpers subdirectories to filters 36 | testhelpers_filters=$(find ./testhelpers -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | awk '{printf "testhelpers/%s: \"testhelpers/%s/**\"\n", $1, $1}') 37 | echo "filters<> $GITHUB_OUTPUT 38 | echo "$filters" >> $GITHUB_OUTPUT 39 | echo "$testhelpers_filters" >> $GITHUB_OUTPUT 40 | echo "EOF" >> $GITHUB_OUTPUT 41 | shell: bash 42 | 43 | - name: Filter changes 44 | id: filter 45 | uses: dorny/paths-filter@v3 46 | with: 47 | filters: ${{ steps.filter-setup.outputs.filters }} 48 | outputs: 49 | packages: ${{ steps.filter.outputs.changes || '[]' }} 50 | 51 | lint: 52 | needs: changes 53 | runs-on: ubuntu-latest 54 | strategy: 55 | matrix: 56 | package: ${{ fromJSON(needs.changes.outputs.packages || '[]') }} 57 | steps: 58 | - name: Fetch Repository 59 | uses: actions/checkout@v4 60 | - name: Run golangci-lint 61 | uses: reviewdog/action-golangci-lint@v2 62 | with: 63 | golangci_lint_flags: "--tests=false --timeout=5m" 64 | workdir: ${{ matrix.package }} 65 | fail_level: "warning" 66 | filter_mode: nofilter 67 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter (All) 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | 9 | jobs: 10 | changes: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | pull-requests: read 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v4 17 | 18 | - name: Generate filters 19 | id: filter-setup 20 | run: | 21 | filters=$(find . -maxdepth 1 -type d ! -path ./.git ! -path . ! -path ./testhelpers -exec basename {} \; | grep -v '^\.' | awk '{printf "%s: \"%s/**\"\n", $1, $1}') 22 | echo "filters<> $GITHUB_OUTPUT 23 | echo "$filters" >> $GITHUB_OUTPUT 24 | echo "EOF" >> $GITHUB_OUTPUT 25 | shell: bash 26 | - name: Filter changes 27 | id: filter 28 | uses: dorny/paths-filter@v3 29 | with: 30 | filters: ${{ steps.filter-setup.outputs.filters }} 31 | 32 | outputs: 33 | packages: ${{ steps.filter.outputs.changes || '[]' }} 34 | 35 | release-drafter: 36 | needs: changes 37 | runs-on: ubuntu-latest 38 | timeout-minutes: 30 39 | if: needs.changes.outputs.packages != '[]' # Ensure job runs only if there are changes 40 | env: 41 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 42 | strategy: 43 | matrix: 44 | package: ${{ fromJSON(needs.changes.outputs.packages || '[]') }} 45 | steps: 46 | - name: Checkout repository 47 | uses: actions/checkout@v4 48 | 49 | - name: Generate dynamic config from template 50 | id: generate-config 51 | run: | 52 | folder="${{ matrix.package }}" 53 | sed "s|{{FOLDER}}|$folder|g" .github/release-drafter-template.yml > .github/release-drafter-$folder.yml 54 | echo "config<> $GITHUB_OUTPUT 55 | cat .github/release-drafter-$folder.yml >> $GITHUB_OUTPUT 56 | echo "EOF" >> $GITHUB_OUTPUT 57 | 58 | - name: Use dynamic release-drafter configuration 59 | uses: ReneWerner87/release-drafter@6dec4ceb1fb86b6514f11a2e7a39e1dedce709d0 60 | with: 61 | config: ${{ steps.generate-config.outputs.config }} 62 | -------------------------------------------------------------------------------- /.github/workflows/sync-docs.yml: -------------------------------------------------------------------------------- 1 | name: 'Sync docs' 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | paths: 9 | - '**/*.md' 10 | release: 11 | types: [published] 12 | branches: 13 | - '*/v[0-9]+.[0-9]+.[0-9]+' 14 | 15 | jobs: 16 | sync-docs: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | ref: ${{ github.event.pull_request.head.sha }} 23 | fetch-depth: 2 24 | 25 | - name: Setup Node.js environment 26 | uses: actions/setup-node@v4 27 | with: 28 | node-version: '18' 29 | 30 | - name: Install JQ 31 | run: sudo apt-get install jq 32 | 33 | - name: Sync docs 34 | run: ./.github/scripts/sync_docs.sh 35 | env: 36 | EVENT: ${{ github.event_name }} 37 | TAG_NAME: ${{ github.ref_name }} 38 | TOKEN: ${{ secrets.DOC_SYNC_TOKEN }} 39 | -------------------------------------------------------------------------------- /.github/workflows/test-aerospike.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'aerospike/**' 8 | pull_request: 9 | paths: 10 | - 'aerospike/**' 11 | name: "Tests Aerospike" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_AEROSPIKE_IMAGE: aerospike/aerospike-server:latest 30 | run: cd ./aerospike && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-arangodb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'arangodb/**' 8 | pull_request: 9 | paths: 10 | - 'arangodb/**' 11 | name: "Tests ArangoDB" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_ARANGODB_IMAGE: arangodb:latest 30 | run: cd ./arangodb && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-azureblob.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'azureblob/**' 8 | pull_request: 9 | paths: 10 | - 'azureblob/**' 11 | name: "Tests Azure Blob" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_AZURITE_IMAGE: mcr.microsoft.com/azure-storage/azurite:latest 30 | run: cd ./azureblob && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-badger.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'badger/**' 8 | pull_request: 9 | paths: 10 | - 'badger/**' 11 | name: "Tests Badger" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.19.x 18 | - 1.20.x 19 | - 1.21.x 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Test Badger 29 | run: cd ./badger && go test ./... -v -race 30 | -------------------------------------------------------------------------------- /.github/workflows/test-bbolt.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'bbolt/**' 8 | pull_request: 9 | paths: 10 | - 'bbolt/**' 11 | name: "Tests Bbolt" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.19.x 19 | - 1.20.x 20 | - 1.21.x 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Run Test 29 | run: cd ./bbolt && go test ./... -v -race 30 | -------------------------------------------------------------------------------- /.github/workflows/test-cassandra.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'cassandra/**' 8 | pull_request: 9 | paths: 10 | - 'cassandra/**' 11 | name: 'Tests Cassandra' 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_CASSANDRA_IMAGE: cassandra:latest 30 | run: cd ./cassandra && go clean -testcache && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-clickhouse.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'clickhouse/**' 8 | pull_request: 9 | paths: 10 | - 'clickhouse/**' 11 | name: 'Tests Clickhouse' 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_CLICKHOUSE_IMAGE: clickhouse/clickhouse-server:23-alpine 30 | run: cd ./clickhouse && go clean -testcache && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-cloudflarekv.yml: -------------------------------------------------------------------------------- 1 | name: Tests CloudflareKV 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - main 8 | paths: 9 | - 'cloudflarekv/**' 10 | pull_request: 11 | paths: 12 | - 'cloudflarekv/**' 13 | 14 | jobs: 15 | Tests: 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | go-version: 20 | - 1.21.x 21 | - 1.22.x 22 | steps: 23 | - name: Checkout Repository 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup Go 27 | uses: actions/setup-go@v5 28 | with: 29 | go-version: ${{ matrix.go-version }} 30 | 31 | - name: Setup Node.js 32 | uses: actions/setup-node@v4 33 | with: 34 | node-version: '18' 35 | 36 | - name: Start Wrangler Dev 37 | run: | 38 | .github/scripts/initialize-wrangler.sh 39 | cd cloudflarekv && npx wrangler dev & 40 | npx wait-on tcp:8787 41 | 42 | - name: Run Go Tests 43 | run: cd cloudflarekv && go test ./... -v -race 44 | -------------------------------------------------------------------------------- /.github/workflows/test-coherence.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'coherence/**' 8 | pull_request: 9 | paths: 10 | - 'coherence/**' 11 | name: "Tests Coherence" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_COHERENCE_IMAGE: "ghcr.io/oracle/coherence-ce:25.03.1-graal" 30 | run: cd ./coherence && COHERENCE_SESSION_DEBUG=true go clean -testcache && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-couchbase.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'couchbase/**' 8 | pull_request: 9 | paths: 10 | - 'couchbase/**' 11 | name: "Tests Couchbase" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_COUCHBASE_IMAGE: couchbase:enterprise-7.6.5 30 | run: cd ./couchbase && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-dynamodb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'dynamodb/**' 8 | pull_request: 9 | paths: 10 | - 'dynamodb/**' 11 | name: "Tests DynamoDB" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | services: 16 | mongo: 17 | image: 'amazon/dynamodb-local:latest' 18 | ports: 19 | - '8000:8000' 20 | strategy: 21 | matrix: 22 | go-version: 23 | - 1.23.x 24 | - 1.24.x 25 | steps: 26 | - name: Fetch Repository 27 | uses: actions/checkout@v4 28 | - name: Install Go 29 | uses: actions/setup-go@v5 30 | with: 31 | go-version: '${{ matrix.go-version }}' 32 | - name: Run Test 33 | env: 34 | TEST_DYNAMODB_IMAGE: amazon/dynamodb-local:latest 35 | run: cd ./dynamodb && go test ./... -v -race 36 | -------------------------------------------------------------------------------- /.github/workflows/test-etcd.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'etcd/**' 8 | pull_request: 9 | paths: 10 | - 'etcd/**' 11 | name: "Tests Etcd" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.19.x 19 | - 1.20.x 20 | - 1.21.x 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install etcd 25 | run: | 26 | docker run -d --name Etcd-server \ 27 | --publish 2379:2379 \ 28 | --publish 2380:2380 \ 29 | --env ALLOW_NONE_AUTHENTICATION=yes \ 30 | --env ETCD_ADVERTISE_CLIENT_URLS=http://etcd-server:2379 \ 31 | bitnami/etcd:latest 32 | 33 | - name: Install Go 34 | uses: actions/setup-go@v5 35 | with: 36 | go-version: '${{ matrix.go-version }}' 37 | - name: Run Test 38 | run: cd ./etcd && go test ./... -v -race 39 | -------------------------------------------------------------------------------- /.github/workflows/test-leveldb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'leveldb/**' 8 | pull_request: 9 | paths: 10 | - 'leveldb/**' 11 | name: "Tests LevelDB" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.23.x 18 | - 1.24.x 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Test LevelDB 28 | run: cd ./leveldb && go test ./... -v -race 29 | -------------------------------------------------------------------------------- /.github/workflows/test-memcache.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'memcache/**' 8 | pull_request: 9 | paths: 10 | - 'memcache/**' 11 | name: "Tests Memcache" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_MEMCACHED_IMAGE: "memcached:latest" 30 | run: cd ./memcache && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-memory.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'memory/**' 8 | pull_request: 9 | paths: 10 | - 'memory/**' 11 | name: "Tests Local Storage" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.19.x 18 | - 1.20.x 19 | - 1.21.x 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Test Memory 29 | run: cd ./memory && go test ./... -v -race 30 | -------------------------------------------------------------------------------- /.github/workflows/test-minio.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'minio/**' 8 | pull_request: 9 | paths: 10 | - 'minio/**' 11 | name: "Tests Minio" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_MINIO_IMAGE: docker.io/minio/minio:latest 30 | run: cd ./minio && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-mockstorage.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'mockstorage/**' 8 | pull_request: 9 | paths: 10 | - 'mockstorage/**' 11 | name: "Tests Local Storage" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.21.x 18 | - 1.22.x 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Test Mockstorage 28 | run: cd ./mockstorage && go test ./... -v -race 29 | -------------------------------------------------------------------------------- /.github/workflows/test-mongodb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'mongodb/**' 8 | pull_request: 9 | paths: 10 | - 'mongodb/**' 11 | name: "Tests Mongodb" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_MONGODB_IMAGE: docker.io/mongo:7 30 | run: cd ./mongodb && go test ./... -v -race 31 | 32 | -------------------------------------------------------------------------------- /.github/workflows/test-mssql.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'mssql/**' 8 | pull_request: 9 | paths: 10 | - 'mssql/**' 11 | name: "Tests MSSQL" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | services: 16 | mssql: 17 | image: 'mcmoe/mssqldocker:latest' 18 | ports: 19 | - '1433:1433' 20 | env: 21 | ACCEPT_EULA: Y 22 | SA_PASSWORD: MsSql!1234 23 | MSSQL_DB: master 24 | MSSQL_USER: sa 25 | MSSQL_PASSWORD: MsSql!1234 26 | options: >- 27 | --health-cmd "/opt/mssql-tools/bin/sqlcmd -U sa -P $SA_PASSWORD -Q 'select 1' -b -o /dev/null" 28 | --health-interval 1s 29 | --health-timeout 30s 30 | --health-start-period 10s 31 | --health-retries 20 32 | strategy: 33 | matrix: 34 | go-version: 35 | - 1.19.x 36 | - 1.20.x 37 | - 1.21.x 38 | steps: 39 | - name: Fetch Repository 40 | uses: actions/checkout@v4 41 | - name: Install Go 42 | uses: actions/setup-go@v5 43 | with: 44 | go-version: '${{ matrix.go-version }}' 45 | - name: Run Test 46 | run: cd ./mssql && go test ./... -v -race 47 | env: 48 | MSSQL_DATABASE: master 49 | MSSQL_USERNAME: sa 50 | MSSQL_PASSWORD: MsSql!1234 51 | -------------------------------------------------------------------------------- /.github/workflows/test-mysql.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'mysql/**' 8 | pull_request: 9 | paths: 10 | - 'mysql/**' 11 | name: "Tests MySQL" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_MYSQL_IMAGE: docker.io/mysql:9 30 | run: cd ./mysql && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-nats.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'nats/**' 8 | pull_request: 9 | paths: 10 | - 'nats/**' 11 | name: "Tests Nats Driver" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.23.x 18 | - 1.24.x 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Test Nats 28 | env: 29 | TEST_NATS_IMAGE: "nats:2-alpine" 30 | run: cd ./nats && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-neo4j.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'neo4j/**' 8 | pull_request: 9 | paths: 10 | - 'neo4j/**' 11 | name: "Tests Neo4j" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | steps: 20 | - name: Fetch Repository 21 | uses: actions/checkout@v4 22 | - name: Install Go 23 | uses: actions/setup-go@v5 24 | with: 25 | go-version: '${{ matrix.go-version }}' 26 | - name: Run Test 27 | run: cd ./neo4j && go test ./... -v -race 28 | -------------------------------------------------------------------------------- /.github/workflows/test-pebble.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - "pebble/**" 8 | pull_request: 9 | paths: 10 | - "pebble/**" 11 | name: "Tests pebble" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.19.x 18 | - 1.20.x 19 | - 1.21.x 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Test Pebble 29 | run: cd ./pebble && go test ./... -v -race 30 | -------------------------------------------------------------------------------- /.github/workflows/test-postgres.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'postgres/**' 8 | pull_request: 9 | paths: 10 | - 'postgres/**' 11 | name: "Tests Postgres" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_POSTGRES_IMAGE: "docker.io/postgres:16-alpine" 30 | run: cd ./postgres && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-redis.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'redis/**' 8 | pull_request: 9 | paths: 10 | - 'redis/**' 11 | name: "Tests Redis" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | redis: 21 | - '6' 22 | - '7' 23 | steps: 24 | - name: Fetch Repository 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup Redis Cluster 28 | uses: vishnudxb/redis-cluster@1.0.9 29 | with: 30 | master1-port: 7000 31 | master2-port: 7001 32 | master3-port: 7002 33 | slave1-port: 7003 34 | slave2-port: 7004 35 | slave3-port: 7005 36 | sleep-duration: 10 37 | 38 | - name: Wait for Redis to Start 39 | run: sleep 15 40 | 41 | - name: Install Go 42 | uses: actions/setup-go@v5 43 | with: 44 | go-version: '${{ matrix.go-version }}' 45 | 46 | - name: Run Test 47 | env: 48 | TEST_REDIS_IMAGE: "docker.io/redis:${{ matrix.redis }}" 49 | run: cd ./redis && go test ./... -v -race 50 | -------------------------------------------------------------------------------- /.github/workflows/test-ristretto.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'ristretto/**' 8 | pull_request: 9 | paths: 10 | - 'ristretto/**' 11 | name: "Tests Ristretto" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.19.x 19 | - 1.20.x 20 | - 1.21.x 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Run Test 29 | run: cd ./ristretto && go test ./... -v -race 30 | -------------------------------------------------------------------------------- /.github/workflows/test-rueidis.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'rueidis/**' 8 | pull_request: 9 | paths: 10 | - 'rueidis/**' 11 | name: "Tests Rueidis" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | redis: 21 | - '6' 22 | - '7' 23 | steps: 24 | - name: Fetch Repository 25 | uses: actions/checkout@v4 26 | 27 | - name: Setup Redis Cluster 28 | uses: vishnudxb/redis-cluster@1.0.9 29 | with: 30 | master1-port: 7000 31 | master2-port: 7001 32 | master3-port: 7002 33 | slave1-port: 7003 34 | slave2-port: 7004 35 | slave3-port: 7005 36 | sleep-duration: 10 37 | 38 | - name: Install Go 39 | uses: actions/setup-go@v5 40 | with: 41 | go-version: '${{ matrix.go-version }}' 42 | 43 | - name: Run Test 44 | env: 45 | TEST_REDIS_IMAGE: "docker.io/redis:${{ matrix.redis }}" 46 | run: cd ./rueidis && go test ./... -v -race 47 | -------------------------------------------------------------------------------- /.github/workflows/test-s3.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 's3/**' 8 | pull_request: 9 | paths: 10 | - 's3/**' 11 | name: "Tests S3" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | - name: Run Test 28 | env: 29 | TEST_MINIO_IMAGE: docker.io/minio/minio:latest 30 | run: cd ./s3 && go test ./... -v -race 31 | -------------------------------------------------------------------------------- /.github/workflows/test-scylladb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'scylladb/**' 8 | pull_request: 9 | paths: 10 | - 'scylladb/**' 11 | 12 | name: "Tests ScyllaDb" 13 | 14 | jobs: 15 | Tests: 16 | runs-on: ubuntu-latest 17 | 18 | strategy: 19 | matrix: 20 | go-version: 21 | - 1.23.x 22 | - 1.24.x 23 | 24 | steps: 25 | - name: Fetch Repository 26 | uses: actions/checkout@v4 27 | 28 | - name: Install Go 29 | uses: actions/setup-go@v5 30 | with: 31 | go-version: '${{ matrix.go-version }}' 32 | 33 | - name: Run Test 34 | env: 35 | TEST_SCYLLADB_IMAGE: "scylladb/scylla:6.2" 36 | run: cd ./scylladb && go test ./... -v -race 37 | -------------------------------------------------------------------------------- /.github/workflows/test-sqlite3.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'sqlite3/**' 8 | pull_request: 9 | paths: 10 | - 'sqlite3/**' 11 | name: "Tests Sqlite3" 12 | jobs: 13 | Tests: 14 | strategy: 15 | matrix: 16 | go-version: 17 | - 1.19.x 18 | - 1.20.x 19 | - 1.21.x 20 | runs-on: ubuntu-latest 21 | steps: 22 | - name: Fetch Repository 23 | uses: actions/checkout@v4 24 | - name: Install Go 25 | uses: actions/setup-go@v5 26 | with: 27 | go-version: '${{ matrix.go-version }}' 28 | - name: Test SQLite3 - with -race check 29 | if: runner.os != 'Windows' 30 | run: cd ./sqlite3 && go test ./... -v -race 31 | - name: Test SQLite3 - without -race check 32 | if: runner.os == 'Windows' 33 | run: cd ./sqlite3 && go test ./... -v 34 | -------------------------------------------------------------------------------- /.github/workflows/test-surrealdb.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'surrealdb/**' 8 | pull_request: 9 | paths: 10 | - 'surrealdb/**' 11 | name: "Tests SurrealDB" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | steps: 21 | - name: Fetch Repository 22 | uses: actions/checkout@v4 23 | - name: Install Go 24 | uses: actions/setup-go@v5 25 | with: 26 | go-version: '${{ matrix.go-version }}' 27 | 28 | - name: Run Test 29 | env: 30 | TEST_SURREALDB_IMAGE: surrealdb/surrealdb:latest 31 | run: cd ./surrealdb && go test ./... -v -race -------------------------------------------------------------------------------- /.github/workflows/test-teshelpers-redis.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'testhelpers/redis/**' 8 | pull_request: 9 | paths: 10 | - 'testhelpers/redis/**' 11 | name: "Tests TestHelper Redis" 12 | jobs: 13 | Tests: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | go-version: 18 | - 1.23.x 19 | - 1.24.x 20 | redis: 21 | - '6' 22 | - '7' 23 | steps: 24 | - name: Fetch Repository 25 | uses: actions/checkout@v4 26 | 27 | - name: Install Go 28 | uses: actions/setup-go@v5 29 | with: 30 | go-version: '${{ matrix.go-version }}' 31 | 32 | - name: Run Test 33 | env: 34 | TEST_REDIS_IMAGE: "docker.io/redis:${{ matrix.redis }}" 35 | working-directory: testhelpers/redis 36 | run: go test ./... -v -race 37 | -------------------------------------------------------------------------------- /.github/workflows/test-valkey.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | - main 6 | paths: 7 | - 'valkey/**' 8 | pull_request: 9 | paths: 10 | - 'valkey/**' 11 | - '.github/workflows/test-valkey.yml' 12 | name: "Tests Valkey" 13 | jobs: 14 | Tests: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | go-version: 19 | - 1.23.x 20 | - 1.24.x 21 | valkey: 22 | - '7' 23 | - '8' 24 | steps: 25 | - name: Fetch Repository 26 | uses: actions/checkout@v4 27 | 28 | - name: Setup Valkey Cluster 29 | uses: vishnudxb/redis-cluster@1.0.9 30 | with: 31 | master1-port: 7000 32 | master2-port: 7001 33 | master3-port: 7002 34 | slave1-port: 7003 35 | slave2-port: 7004 36 | slave3-port: 7005 37 | sleep-duration: 10 38 | 39 | - name: Install Go 40 | uses: actions/setup-go@v5 41 | with: 42 | go-version: '${{ matrix.go-version }}' 43 | 44 | - name: Run Test 45 | env: 46 | TEST_VALKEY_IMAGE: "valkey/valkey:${{ matrix.valkey }}" 47 | run: cd ./valkey && go test ./... -v -race 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | *.tmp 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # IDE files 16 | .vscode 17 | .DS_Store 18 | .idea 19 | 20 | # Misc 21 | *.fiber.gz 22 | *.fasthttp.gz 23 | *.pprof 24 | *.workspace 25 | /tmp/ 26 | 27 | # Dependencies 28 | /vendor/ 29 | vendor/ 30 | vendor 31 | /Godeps/ 32 | node_modules/ 33 | 34 | # Go workspace file 35 | go.work.sum 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Fiber 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MIGRATE.md: -------------------------------------------------------------------------------- 1 | This document contains instructions for migrating to various storage versions. 2 | 3 | ### 0.1 -> 0.2 4 | v0.2 fixes [a bug](https://github.com/gofiber/fiber/issues/1258) in MYSQL, Postgres and Arangodb in which 5 | inserting non-UTF8 characters would trigger a panic due to the values being saved in a TEXT column instead of a 6 | BYTEA/BLOB column. Migration instructions (note you may need to adjust the table names if you have supplied a custom 7 | config to the storage): 8 | 9 | **Postgres** 10 | ```sql 11 | ALTER TABLE fiber_storage 12 | ALTER COLUMN v TYPE BYTEA USING v::bytea; 13 | ``` 14 | 15 | **MYSQL** 16 | ```sql 17 | ALTER TABLE fiber_storage MODIFY COLUMN v BLOB; 18 | ``` 19 | 20 | **Arangodb** 21 | 22 | No migration other then updating the library is necessary. 23 | -------------------------------------------------------------------------------- /aerospike/config.go: -------------------------------------------------------------------------------- 1 | package aerospike 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/aerospike/aerospike-client-go/v8" 7 | ) 8 | 9 | // Config defines the config for storage. 10 | type Config struct { 11 | // Hosts is a list of Aerospike server hosts 12 | Hosts []*aerospike.Host 13 | 14 | // Namespace is the Aerospike namespace 15 | Namespace string 16 | 17 | // SetName is the Aerospike Set name 18 | SetName string 19 | 20 | // Reset clears any existing keys in existing Set 21 | Reset bool 22 | 23 | // Expiration is the default expiration time of entries 24 | Expiration time.Duration 25 | 26 | // SchemaVersion indicates the schema version to use 27 | SchemaVersion int 28 | 29 | // SchemaDescription provides additional info about the schema 30 | SchemaDescription string 31 | 32 | // ForceSchemaUpdate forces schema update even if version matches 33 | ForceSchemaUpdate bool 34 | 35 | // Initial host connection timeout duration. The timeout when opening a connection 36 | // to the server host for the first time. 37 | InitialConnectionTimeout time.Duration 38 | } 39 | 40 | // ConfigDefault is the default config 41 | var ConfigDefault = Config{ 42 | Hosts: []*aerospike.Host{aerospike.NewHost("localhost", 3000)}, 43 | Namespace: "test", // Default namespace 44 | SetName: "fiber", 45 | Reset: false, 46 | Expiration: 1 * time.Hour, 47 | SchemaVersion: 1, 48 | SchemaDescription: "Default Fiber storage schema", 49 | ForceSchemaUpdate: false, 50 | InitialConnectionTimeout: 10 * time.Second, 51 | } 52 | 53 | // Helper function to set default values 54 | func configDefault(config ...Config) Config { 55 | // Return default config if nothing provided 56 | if len(config) < 1 { 57 | return ConfigDefault 58 | } 59 | 60 | // Override default config 61 | cfg := config[0] 62 | 63 | // Set default values for missing fields 64 | if cfg.Hosts == nil { 65 | cfg.Hosts = ConfigDefault.Hosts 66 | } 67 | if cfg.Namespace == "" { 68 | cfg.Namespace = ConfigDefault.Namespace 69 | } 70 | if cfg.SetName == "" { 71 | cfg.SetName = ConfigDefault.SetName 72 | } 73 | // Reset is a boolean, so we can't check for zero value 74 | // It's maintained as-is from user config 75 | if cfg.Expiration == 0 { 76 | cfg.Expiration = ConfigDefault.Expiration 77 | } 78 | if cfg.SchemaVersion == 0 { 79 | cfg.SchemaVersion = ConfigDefault.SchemaVersion 80 | } 81 | if cfg.SchemaDescription == "" { 82 | cfg.SchemaDescription = ConfigDefault.SchemaDescription 83 | } 84 | if cfg.InitialConnectionTimeout == 0 { 85 | cfg.InitialConnectionTimeout = ConfigDefault.InitialConnectionTimeout 86 | } 87 | 88 | return cfg 89 | } 90 | -------------------------------------------------------------------------------- /arangodb/config.go: -------------------------------------------------------------------------------- 1 | package arangodb 2 | 3 | import ( 4 | "strings" 5 | "time" 6 | ) 7 | 8 | // Config defines the config for storage. 9 | type Config struct { 10 | // Host name where the DB is hosted 11 | // 12 | // Optional. Default is "http://127.0.0.1" 13 | Host string 14 | 15 | // Port where the DB is listening on 16 | // 17 | // Optional. Default is 8529 18 | Port int 19 | 20 | // Server username 21 | // 22 | // Optional. Default is "" 23 | Username string 24 | 25 | // Server password 26 | // 27 | // Optional. Default is "" 28 | Password string 29 | 30 | // Database name 31 | // 32 | // Optional. Default is "fiber" 33 | Database string 34 | 35 | // Collection name 36 | // 37 | // Optional. Default is "fiber_storage" 38 | Collection string 39 | 40 | // Reset clears any existing keys in existing collection 41 | // 42 | // Optional. Default is false 43 | Reset bool 44 | // Time before deleting expired keys 45 | // 46 | // Optional. Default is 10 * time.Second 47 | GCInterval time.Duration 48 | } 49 | 50 | // ConfigDefault is the default config 51 | var ConfigDefault = Config{ 52 | Host: "http://127.0.0.1", 53 | Port: 8529, 54 | Database: "fiber", 55 | Collection: "fiber_storage", 56 | Reset: false, 57 | GCInterval: 10 * time.Second, 58 | } 59 | 60 | // Helper function to set default values 61 | func configDefault(config ...Config) Config { 62 | // Return default config if nothing provided 63 | if len(config) < 1 { 64 | return ConfigDefault 65 | } 66 | 67 | // Override default config 68 | cfg := config[0] 69 | 70 | // Set default values 71 | if cfg.Host == "" { 72 | cfg.Host = ConfigDefault.Host 73 | } else { 74 | if !strings.HasPrefix(cfg.Host, "http") { 75 | panic("Host should start with `http://` or `https://`") 76 | } 77 | } 78 | if cfg.Port <= 0 { 79 | cfg.Port = ConfigDefault.Port 80 | } 81 | if cfg.Database == "" { 82 | cfg.Database = ConfigDefault.Database 83 | } 84 | if cfg.Collection == "" { 85 | cfg.Collection = ConfigDefault.Collection 86 | } 87 | 88 | if int(cfg.GCInterval.Seconds()) <= 0 { 89 | cfg.GCInterval = ConfigDefault.GCInterval 90 | } 91 | return cfg 92 | } 93 | -------------------------------------------------------------------------------- /arangodb/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/arangodb/v2 2 | 3 | go 1.23.0 4 | 5 | 6 | require ( 7 | github.com/arangodb/go-driver v1.6.6 8 | github.com/gofiber/utils/v2 v2.0.0-beta.3 9 | github.com/stretchr/testify v1.10.0 10 | github.com/testcontainers/testcontainers-go v0.37.0 11 | github.com/testcontainers/testcontainers-go/modules/arangodb v0.37.0 12 | ) 13 | 14 | require ( 15 | dario.cat/mergo v1.0.1 // indirect 16 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 17 | github.com/Microsoft/go-winio v0.6.2 // indirect 18 | github.com/arangodb/go-velocypack v0.0.0-20200318135517-5af53c29c67e // indirect 19 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 20 | github.com/containerd/log v0.1.0 // indirect 21 | github.com/containerd/platforms v0.2.1 // indirect 22 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 23 | github.com/davecgh/go-spew v1.1.1 // indirect 24 | github.com/distribution/reference v0.6.0 // indirect 25 | github.com/docker/docker v28.0.1+incompatible // indirect 26 | github.com/docker/go-connections v0.5.0 // indirect 27 | github.com/docker/go-units v0.5.0 // indirect 28 | github.com/ebitengine/purego v0.8.2 // indirect 29 | github.com/felixge/httpsnoop v1.0.4 // indirect 30 | github.com/go-logr/logr v1.4.2 // indirect 31 | github.com/go-logr/stdr v1.2.2 // indirect 32 | github.com/go-ole/go-ole v1.2.6 // indirect 33 | github.com/gogo/protobuf v1.3.2 // indirect 34 | github.com/google/uuid v1.6.0 // indirect 35 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect 36 | github.com/klauspost/compress v1.17.4 // indirect 37 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 38 | github.com/magiconair/properties v1.8.10 // indirect 39 | github.com/moby/docker-image-spec v1.3.1 // indirect 40 | github.com/moby/patternmatcher v0.6.0 // indirect 41 | github.com/moby/sys/sequential v0.5.0 // indirect 42 | github.com/moby/sys/user v0.1.0 // indirect 43 | github.com/moby/sys/userns v0.1.0 // indirect 44 | github.com/moby/term v0.5.0 // indirect 45 | github.com/morikuni/aec v1.0.0 // indirect 46 | github.com/opencontainers/go-digest v1.0.0 // indirect 47 | github.com/opencontainers/image-spec v1.1.1 // indirect 48 | github.com/pkg/errors v0.9.1 // indirect 49 | github.com/pmezard/go-difflib v1.0.0 // indirect 50 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 51 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 52 | github.com/sirupsen/logrus v1.9.3 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sys v0.32.0 // indirect 63 | google.golang.org/grpc v1.70.0 // indirect 64 | gopkg.in/yaml.v3 v3.0.1 // indirect 65 | ) 66 | -------------------------------------------------------------------------------- /azureblob/config.go: -------------------------------------------------------------------------------- 1 | package azureblob 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // Config defines the config for storage. 10 | type Config struct { 11 | // Storage account name. 12 | Account string 13 | // Container name. 14 | Container string 15 | // Storage endpoint. 16 | // Optional. Default: "https://STORAGEACCOUNTNAME.blob.core.windows.net" 17 | Endpoint string 18 | // Request timeout. 19 | // Optional. Default is 0 (no timeout) 20 | RequestTimeout time.Duration 21 | // Reset clears any existing keys in existing container. 22 | // Optional. Default is false 23 | Reset bool 24 | // Credentials overrides AWS access key and AWS secret access key. Not recommended. 25 | // Optional. Default is Credentials{} 26 | Credentials Credentials 27 | // The maximum number of times requests that encounter retryable failures should be attempted. 28 | // Optional. Default is 3 29 | MaxAttempts int 30 | } 31 | 32 | // Credentials are the azure storage account access keys 33 | type Credentials struct { 34 | Account string 35 | Key string 36 | } 37 | 38 | // ConfigDefault is the default config 39 | var ConfigDefault = Config{ 40 | Account: "", 41 | Container: "", 42 | Endpoint: "", 43 | RequestTimeout: 0, 44 | Reset: false, 45 | MaxAttempts: 3, 46 | } 47 | 48 | // Helper function to set default values 49 | func configure(config ...Config) Config { 50 | // Return default config if nothing provided 51 | if len(config) < 1 { 52 | return ConfigDefault 53 | } 54 | // Override default config 55 | cfg := config[0] 56 | valid, err := validateConfig(cfg) 57 | if err != nil || !valid { 58 | panic(fmt.Sprintf("invalid config:, %v", err)) 59 | } 60 | if cfg.Endpoint == "" { 61 | cfg.Endpoint = "https://" + cfg.Account + ".blob.core.windows.net" 62 | } 63 | return cfg 64 | } 65 | 66 | func validateConfig(config Config) (bool, error) { 67 | if config.Credentials.Account == "" || config.Credentials.Key == "" { 68 | err := errors.New("credentials must not be empty") 69 | return false, err 70 | } 71 | if config.Account == "" || config.Container == "" { 72 | err := errors.New("invalid account information provided") 73 | return false, err 74 | } 75 | if config.Account != config.Credentials.Account { 76 | err := errors.New("account configuration mismatch") 77 | return false, err 78 | } 79 | return true, nil 80 | } 81 | -------------------------------------------------------------------------------- /badger/.gitignore: -------------------------------------------------------------------------------- 1 | fiber.badger/ 2 | fiber.config.badger/ 3 | fiber.with_options.badger/ 4 | -------------------------------------------------------------------------------- /badger/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: badger 3 | title: Badger 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=badger*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-badger.yml?label=Tests) 9 | 10 | A fast key-value DB using [dgraph-io/badger](https://github.com/dgraph-io/badger) 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | 16 | - [Signatures](#signatures) 17 | - [Installation](#installation) 18 | - [Examples](#examples) 19 | - [Config](#config) 20 | - [Default Config](#default-config) 21 | 22 | ### Signatures 23 | 24 | ```go 25 | func New(config ...Config) Storage 26 | func (s *Storage) Get(key string) ([]byte, error) 27 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 28 | func (s *Storage) Delete(key string) error 29 | func (s *Storage) Reset() error 30 | func (s *Storage) Close() error 31 | func (s *Storage) Conn() *badger.DB 32 | ``` 33 | 34 | ### Installation 35 | 36 | Badger is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 37 | 38 | ```bash 39 | go mod init github.com// 40 | ``` 41 | 42 | And then install the badger implementation: 43 | 44 | ```bash 45 | go get github.com/gofiber/storage/badger/v2 46 | ``` 47 | 48 | ### Examples 49 | 50 | Import the storage package. 51 | 52 | ```go 53 | import "github.com/gofiber/storage/badger/v2" 54 | ``` 55 | 56 | You can use the following possibilities to create a storage: 57 | 58 | ```go 59 | // Initialize default config 60 | store := badger.New() 61 | 62 | // Initialize custom config 63 | store := badger.New(badger.Config{ 64 | Database: "./fiber.badger", 65 | Reset: false, 66 | GCInterval: 10 * time.Second, 67 | }) 68 | ``` 69 | 70 | ### Config 71 | 72 | ```go 73 | type Config struct { 74 | // Database name 75 | // 76 | // Optional. Default is "./fiber.badger" 77 | Database string 78 | 79 | // Reset clears any existing keys in existing Table 80 | // 81 | // Optional. Default is false 82 | Reset bool 83 | 84 | // Time before deleting expired keys 85 | // 86 | // Optional. Default is 10 * time.Second 87 | GCInterval time.Duration 88 | 89 | // BadgerOptions is a way to set options in badger 90 | // 91 | // Optional. Default is badger.DefaultOptions("./fiber.badger") 92 | BadgerOptions badger.Options 93 | 94 | // Logger is the default logger used by badger 95 | // 96 | // Optional. Default is nil 97 | Logger badger.Logger 98 | 99 | // UseLogger define if any logger will be used 100 | // 101 | // Optional. Default is false 102 | UseLogger bool 103 | } 104 | ``` 105 | 106 | ### Default Config 107 | 108 | ```go 109 | var ConfigDefault = Config{ 110 | Database: "./fiber.badger", 111 | Reset: false, 112 | GCInterval: 10 * time.Second, 113 | BadgerOptions: badger.DefaultOptions("./fiber.badger").WithLogger(nil), 114 | Logger: nil, 115 | UseLogger: false, 116 | } 117 | ``` 118 | -------------------------------------------------------------------------------- /badger/badger.go: -------------------------------------------------------------------------------- 1 | package badger 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/dgraph-io/badger/v3" 7 | "github.com/gofiber/utils/v2" 8 | ) 9 | 10 | // Storage interface that is implemented by storage providers 11 | type Storage struct { 12 | db *badger.DB 13 | gcInterval time.Duration 14 | done chan struct{} 15 | } 16 | 17 | // New creates a new memory storage 18 | func New(config ...Config) *Storage { 19 | // Set default config 20 | cfg := configDefault(config...) 21 | 22 | // Set options 23 | opt := cfg.BadgerOptions 24 | 25 | // Open database 26 | db, err := badger.Open(opt) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | if cfg.Reset { 32 | if err := db.DropAll(); err != nil { 33 | panic(err) 34 | } 35 | } 36 | 37 | // Create storage 38 | store := &Storage{ 39 | db: db, 40 | gcInterval: cfg.GCInterval, 41 | done: make(chan struct{}), 42 | } 43 | 44 | // Start garbage collector 45 | go store.gc() 46 | 47 | return store 48 | } 49 | 50 | // Get value by key 51 | func (s *Storage) Get(key string) ([]byte, error) { 52 | if len(key) <= 0 { 53 | return nil, nil 54 | } 55 | var data []byte 56 | err := s.db.View(func(txn *badger.Txn) error { 57 | item, err := txn.Get([]byte(key)) 58 | if err != nil { 59 | return err 60 | } 61 | // item.Value() is only valid within the transaction. 62 | // We can either copy it ourselves or use the ValueCopy() method. 63 | // TODO: Benchmark if it's faster to copy + close tx, 64 | // or to keep the tx open until unmarshalling is done. 65 | data, err = item.ValueCopy(nil) 66 | return err 67 | }) 68 | // If no value was found return false 69 | if err == badger.ErrKeyNotFound { 70 | return nil, nil 71 | } 72 | return data, err 73 | } 74 | 75 | // Set key with value 76 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { 77 | // Ain't Nobody Got Time For That 78 | if len(key) <= 0 || len(val) <= 0 { 79 | return nil 80 | } 81 | 82 | entry := badger.NewEntry(utils.UnsafeBytes(key), val) 83 | if exp != 0 { 84 | entry.WithTTL(exp) 85 | } 86 | return s.db.Update(func(tx *badger.Txn) error { 87 | return tx.SetEntry(entry) 88 | }) 89 | } 90 | 91 | // Delete key by key 92 | func (s *Storage) Delete(key string) error { 93 | // Ain't Nobody Got Time For That 94 | if len(key) <= 0 { 95 | return nil 96 | } 97 | return s.db.Update(func(tx *badger.Txn) error { 98 | return tx.Delete(utils.UnsafeBytes(key)) 99 | }) 100 | } 101 | 102 | // Reset all keys 103 | func (s *Storage) Reset() error { 104 | return s.db.DropAll() 105 | } 106 | 107 | // Close the memory storage 108 | func (s *Storage) Close() error { 109 | s.done <- struct{}{} 110 | return s.db.Close() 111 | } 112 | 113 | func (s *Storage) gc() { 114 | ticker := time.NewTicker(s.gcInterval) 115 | defer ticker.Stop() 116 | 117 | for { 118 | select { 119 | case <-s.done: 120 | return 121 | case <-ticker.C: 122 | _ = s.db.RunValueLogGC(0.7) 123 | } 124 | } 125 | } 126 | 127 | // Return database client 128 | func (s *Storage) Conn() *badger.DB { 129 | return s.db 130 | } 131 | -------------------------------------------------------------------------------- /badger/config.go: -------------------------------------------------------------------------------- 1 | package badger 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/dgraph-io/badger/v3" 7 | ) 8 | 9 | // Config defines the config for storage. 10 | type Config struct { 11 | // Database name 12 | // 13 | // Optional. Default is "./fiber.badger" 14 | Database string 15 | 16 | // Reset clears any existing keys in existing Table 17 | // 18 | // Optional. Default is false 19 | Reset bool 20 | 21 | // Time before deleting expired keys 22 | // 23 | // Optional. Default is 10 * time.Second 24 | GCInterval time.Duration 25 | 26 | // BadgerOptions is a way to set options in badger 27 | // 28 | // Optional. Default is badger.DefaultOptions("./fiber.badger") 29 | BadgerOptions badger.Options 30 | 31 | // Logger is the default logger used by badger 32 | // 33 | // Optional. Default is nil 34 | Logger badger.Logger 35 | 36 | // UseLogger define if any logger will be used 37 | // 38 | // Optional. Default is false 39 | UseLogger bool 40 | } 41 | 42 | const defaultDatabase = "./fiber.badger" 43 | 44 | // ConfigDefault is the default config 45 | var ConfigDefault = Config{ 46 | Database: defaultDatabase, 47 | Reset: false, 48 | GCInterval: 10 * time.Second, 49 | BadgerOptions: badger.DefaultOptions(defaultDatabase).WithLogger(nil), 50 | Logger: nil, 51 | UseLogger: false, 52 | } 53 | 54 | // Helper function to set default values 55 | func configDefault(config ...Config) Config { 56 | // Return default config if nothing provided 57 | if len(config) < 1 { 58 | return ConfigDefault 59 | } 60 | 61 | // Override default config 62 | cfg := config[0] 63 | 64 | // Set default values 65 | if cfg.Database == "" { 66 | cfg.Database = ConfigDefault.Database 67 | } 68 | if int(cfg.GCInterval.Seconds()) <= 0 { 69 | cfg.GCInterval = ConfigDefault.GCInterval 70 | } 71 | overrideLogger := false 72 | // Detecting if no default Badger option was given 73 | // Also detects when a default badger option is given with a custom database name 74 | if cfg.BadgerOptions.ValueLogFileSize <= 0 || cfg.BadgerOptions.Dir == "" || cfg.BadgerOptions.ValueDir == "" || 75 | (cfg.BadgerOptions.Dir == defaultDatabase && cfg.BadgerOptions.Dir != cfg.Database) { 76 | cfg.BadgerOptions = badger.DefaultOptions(cfg.Database) 77 | overrideLogger = true 78 | } 79 | if overrideLogger { 80 | if cfg.UseLogger && cfg.Logger != nil { 81 | cfg.BadgerOptions = cfg.BadgerOptions.WithLogger(cfg.Logger) 82 | } else if !cfg.UseLogger { 83 | cfg.BadgerOptions = cfg.BadgerOptions.WithLogger(nil) 84 | } 85 | } 86 | return cfg 87 | } 88 | -------------------------------------------------------------------------------- /badger/config_test.go: -------------------------------------------------------------------------------- 1 | package badger 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/dgraph-io/badger/v3" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func assertRecoveryPanic(t *testing.T) { 11 | err := recover() 12 | require.Nil(t, nil, err) 13 | } 14 | 15 | func Test_Badger_Only_Name(t *testing.T) { 16 | defer assertRecoveryPanic(t) 17 | testDB := New(Config{ 18 | Database: "fiber.config.badger", 19 | UseLogger: false, 20 | }) 21 | require.Nil(t, testDB.Close()) 22 | } 23 | 24 | func Test_Badger_Options(t *testing.T) { 25 | defer assertRecoveryPanic(t) 26 | testDB := New(Config{ 27 | BadgerOptions: badger.DefaultOptions("fiber.with_options.badger"), 28 | UseLogger: false, 29 | }) 30 | require.Nil(t, testDB.Close()) 31 | } 32 | 33 | func Test_Empty_Config(t *testing.T) { 34 | defer assertRecoveryPanic(t) 35 | testDB := New(Config{}) 36 | require.Nil(t, testDB.Close()) 37 | } 38 | -------------------------------------------------------------------------------- /badger/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/badger/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/dgraph-io/badger/v3 v3.2103.5 7 | github.com/gofiber/utils/v2 v2.0.0-beta.3 8 | github.com/stretchr/testify v1.10.0 9 | ) 10 | 11 | require ( 12 | github.com/cespare/xxhash v1.1.0 // indirect 13 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 14 | github.com/davecgh/go-spew v1.1.1 // indirect 15 | github.com/dgraph-io/ristretto v0.1.1 // indirect 16 | github.com/dustin/go-humanize v1.0.1 // indirect 17 | github.com/gogo/protobuf v1.3.2 // indirect 18 | github.com/golang/glog v1.1.2 // indirect 19 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 20 | github.com/golang/protobuf v1.5.3 // indirect 21 | github.com/golang/snappy v0.0.4 // indirect 22 | github.com/google/flatbuffers v23.5.26+incompatible // indirect 23 | github.com/google/uuid v1.3.1 // indirect 24 | github.com/klauspost/compress v1.16.7 // indirect 25 | github.com/pkg/errors v0.9.1 // indirect 26 | github.com/pmezard/go-difflib v1.0.0 // indirect 27 | go.opencensus.io v0.24.0 // indirect 28 | golang.org/x/net v0.25.0 // indirect 29 | golang.org/x/sys v0.20.0 // indirect 30 | google.golang.org/protobuf v1.33.0 // indirect 31 | gopkg.in/yaml.v3 v3.0.1 // indirect 32 | ) 33 | -------------------------------------------------------------------------------- /bbolt/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: bbolt 3 | title: Bbolt 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=bbolt*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-bbolt.yml?label=Tests) 9 | 10 | A Bbolt storage driver using [etcd-io/bbolt](https://github.com/etcd-io/bbolt). Bolt is a pure Go key/value store inspired by [Howard Chu's](https://twitter.com/hyc_symas) [LMDB project](https://www.symas.com/symas-embedded-database-lmdb). The goal of the project is to provide a simple, fast, and reliable database for projects that don't require a full database server such as Postgres or MySQL. 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | - [Signatures](#signatures) 16 | - [Installation](#installation) 17 | - [Examples](#examples) 18 | - [Config](#config) 19 | - [Default Config](#default-config) 20 | 21 | ### Signatures 22 | ```go 23 | func New(config ...Config) Storage 24 | func (s *Storage) Get(key string) ([]byte, error) 25 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 26 | func (s *Storage) Delete(key string) error 27 | func (s *Storage) Reset() error 28 | func (s *Storage) Close() error 29 | func (s *Storage) Conn() *bbolt.DB 30 | ``` 31 | ### Installation 32 | Bbolt is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 33 | ```bash 34 | go mod init github.com// 35 | ``` 36 | And then install the s3 implementation: 37 | ```bash 38 | go get github.com/gofiber/storage/bbolt/v2 39 | ``` 40 | 41 | ### Examples 42 | Import the storage package. 43 | ```go 44 | import "github.com/gofiber/storage/bbolt/v2" 45 | ``` 46 | 47 | You can use the following possibilities to create a storage: 48 | ```go 49 | // Initialize default config 50 | store := bbolt.New() 51 | 52 | // Initialize custom config 53 | store := bbolt.New(bbolt.Config{ 54 | Database: "my_database.db", 55 | Bucket: "my-bucket", 56 | Reset: false, 57 | }) 58 | ``` 59 | 60 | ### Config 61 | ```go 62 | // Config defines the config for storage. 63 | type Config struct { 64 | // Database path 65 | // 66 | // Optional. Default is "fiber.db" 67 | Database string 68 | 69 | // Bbolt bucket name 70 | // 71 | // Optional. Default is "fiber_storage" 72 | Bucket string 73 | 74 | // Timeout is the amount of time to wait to obtain a file lock. 75 | // Only available on Darwin and Linux. 76 | // 77 | // Optional. Default is 60 * time.Second. 78 | Timeout time.Duration 79 | 80 | // Open database in read-only mode. 81 | // 82 | // Optional. Default is false 83 | ReadOnly bool 84 | 85 | // Reset clears any existing keys in existing Bucket 86 | // 87 | // Optional. Default is false 88 | Reset bool 89 | } 90 | ``` 91 | 92 | ### Default Config 93 | ```go 94 | // ConfigDefault is the default config 95 | var ConfigDefault = Config{ 96 | Database: "fiber.db", 97 | Bucket: "fiber_storage", 98 | Timeout: 60 * time.Second, 99 | ReadOnly: false, 100 | Reset: false, 101 | } 102 | ``` 103 | -------------------------------------------------------------------------------- /bbolt/bbolt.go: -------------------------------------------------------------------------------- 1 | package bbolt 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/gofiber/utils/v2" 7 | "go.etcd.io/bbolt" 8 | ) 9 | 10 | // Storage interface that is implemented by storage providers 11 | type Storage struct { 12 | conn *bbolt.DB 13 | bucket string 14 | } 15 | 16 | // New creates a new storage 17 | func New(config ...Config) *Storage { 18 | // Set default config 19 | cfg := configDefault(config...) 20 | 21 | conn, err := bbolt.Open(cfg.Database, 0o666, &bbolt.Options{ 22 | Timeout: cfg.Timeout, 23 | ReadOnly: cfg.ReadOnly, 24 | }) 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | // Reset bucket if field selected 30 | if cfg.Reset { 31 | if err := removeBucket(cfg, conn); err != nil { 32 | panic(err) 33 | } 34 | } 35 | 36 | // Create bucket if not exists 37 | if err := createBucket(cfg, conn); err != nil { 38 | panic(err) 39 | } 40 | 41 | return &Storage{ 42 | conn: conn, 43 | bucket: cfg.Bucket, 44 | } 45 | } 46 | 47 | // Get value by key 48 | func (s *Storage) Get(key string) ([]byte, error) { 49 | if len(key) <= 0 { 50 | return nil, nil 51 | } 52 | 53 | var value []byte 54 | 55 | err := s.conn.View(func(tx *bbolt.Tx) error { 56 | b := tx.Bucket(utils.UnsafeBytes(s.bucket)) 57 | value = b.Get(utils.UnsafeBytes(key)) 58 | 59 | return nil 60 | }) 61 | 62 | return value, err 63 | } 64 | 65 | // Set key with value 66 | func (s *Storage) Set(key string, value []byte, exp time.Duration) error { 67 | if len(key) <= 0 || len(value) <= 0 { 68 | return nil 69 | } 70 | 71 | return s.conn.Update(func(tx *bbolt.Tx) error { 72 | b := tx.Bucket(utils.UnsafeBytes(s.bucket)) 73 | 74 | return b.Put(utils.UnsafeBytes(key), value) 75 | }) 76 | } 77 | 78 | // Delete entry by key 79 | func (s *Storage) Delete(key string) error { 80 | if len(key) <= 0 { 81 | return nil 82 | } 83 | 84 | return s.conn.Update(func(tx *bbolt.Tx) error { 85 | b := tx.Bucket(utils.UnsafeBytes(s.bucket)) 86 | 87 | return b.Delete(utils.UnsafeBytes(key)) 88 | }) 89 | } 90 | 91 | // Reset all entries 92 | func (s *Storage) Reset() error { 93 | return s.conn.Update(func(tx *bbolt.Tx) error { 94 | b := tx.Bucket(utils.UnsafeBytes(s.bucket)) 95 | 96 | return b.ForEach(func(k, _ []byte) error { 97 | return b.Delete(k) 98 | }) 99 | }) 100 | } 101 | 102 | // Close the database 103 | func (s *Storage) Close() error { 104 | return s.conn.Close() 105 | } 106 | 107 | // Return database client 108 | func (s *Storage) Conn() *bbolt.DB { 109 | return s.conn 110 | } 111 | -------------------------------------------------------------------------------- /bbolt/config.go: -------------------------------------------------------------------------------- 1 | package bbolt 2 | 3 | import "time" 4 | 5 | // Config defines the config for storage. 6 | type Config struct { 7 | // Database path 8 | // 9 | // Optional. Default is "fiber.db" 10 | Database string 11 | 12 | // Bbolt bucket name 13 | // 14 | // Optional. Default is "fiber_storage" 15 | Bucket string 16 | 17 | // Timeout is the amount of time to wait to obtain a file lock. 18 | // Only available on Darwin and Linux. 19 | // 20 | // Optional. Default is set to 60 * time.Second. 21 | Timeout time.Duration 22 | 23 | // Open database in read-only mode. 24 | // 25 | // Optional. Default is false 26 | ReadOnly bool 27 | 28 | // Reset clears any existing keys in existing Bucket 29 | // 30 | // Optional. Default is false 31 | Reset bool 32 | } 33 | 34 | // ConfigDefault is the default config 35 | var ConfigDefault = Config{ 36 | Database: "fiber.db", 37 | Bucket: "fiber_storage", 38 | Timeout: 60 * time.Second, 39 | ReadOnly: false, 40 | Reset: false, 41 | } 42 | 43 | // Helper function to set default values 44 | func configDefault(config ...Config) Config { 45 | // Return default config if nothing provided 46 | if len(config) < 1 { 47 | return ConfigDefault 48 | } 49 | 50 | // Override default config 51 | cfg := config[0] 52 | 53 | // Set default values 54 | if cfg.Database == "" { 55 | cfg.Database = ConfigDefault.Database 56 | } 57 | 58 | if cfg.Bucket == "" { 59 | cfg.Bucket = ConfigDefault.Bucket 60 | } 61 | 62 | return cfg 63 | } 64 | -------------------------------------------------------------------------------- /bbolt/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/bbolt/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/gofiber/utils/v2 v2.0.0-beta.3 7 | github.com/stretchr/testify v1.10.0 8 | go.etcd.io/bbolt v1.3.9 9 | ) 10 | 11 | require ( 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/google/uuid v1.3.1 // indirect 14 | github.com/pmezard/go-difflib v1.0.0 // indirect 15 | golang.org/x/sys v0.11.0 // indirect 16 | gopkg.in/yaml.v3 v3.0.1 // indirect 17 | ) 18 | -------------------------------------------------------------------------------- /bbolt/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/gofiber/utils/v2 v2.0.0-beta.3 h1:pfOhUDDVjBJpkWv6C5jaDyYLvpui7zQ97zpyFFsUOKw= 4 | github.com/gofiber/utils/v2 v2.0.0-beta.3/go.mod h1:jsl17+MsKfwJjM3ONCE9Rzji/j8XNbwjhUVTjzgfDCo= 5 | github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= 6 | github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 7 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 8 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 9 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 10 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 11 | go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= 12 | go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= 13 | golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= 14 | golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= 15 | golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 16 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 17 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 18 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 19 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 20 | -------------------------------------------------------------------------------- /bbolt/utils.go: -------------------------------------------------------------------------------- 1 | package bbolt 2 | 3 | import ( 4 | "errors" 5 | "github.com/gofiber/utils/v2" 6 | "go.etcd.io/bbolt" 7 | ) 8 | 9 | func createBucket(cfg Config, conn *bbolt.DB) error { 10 | return conn.Update(func(tx *bbolt.Tx) error { 11 | _, err := tx.CreateBucketIfNotExists(utils.UnsafeBytes(cfg.Bucket)) 12 | 13 | return err 14 | }) 15 | } 16 | 17 | func removeBucket(cfg Config, conn *bbolt.DB) error { 18 | return conn.Update(func(tx *bbolt.Tx) error { 19 | err := tx.DeleteBucket(utils.UnsafeBytes(cfg.Bucket)) 20 | if errors.Is(err, bbolt.ErrBucketNotFound) { 21 | return nil 22 | } 23 | 24 | return err 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /clickhouse/clickhouse.go: -------------------------------------------------------------------------------- 1 | package clickhouse 2 | 3 | import ( 4 | "context" 5 | "database/sql" 6 | "errors" 7 | "fmt" 8 | "time" 9 | 10 | driver "github.com/ClickHouse/clickhouse-go/v2" 11 | ) 12 | 13 | type Storage struct { 14 | session driver.Conn 15 | context context.Context 16 | table string 17 | } 18 | 19 | // New returns a new [*Storage] given a [Config]. 20 | func New(configuration Config) (*Storage, error) { 21 | cfg, engine, err := defaultConfig(configuration) 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | conn, err := driver.Open(&cfg) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | ctx := context.Background() 32 | 33 | queryWithEngine := fmt.Sprintf(createTableString, engine) 34 | if err := conn.Exec(ctx, queryWithEngine, driver.Named("table", configuration.Table)); err != nil { 35 | return nil, err 36 | } 37 | 38 | if configuration.Clean { 39 | if err := conn.Exec(ctx, resetDataString, driver.Named("table", configuration.Table)); err != nil { 40 | return nil, err 41 | } 42 | } 43 | 44 | if err := conn.Ping(ctx); err != nil { 45 | return nil, err 46 | } 47 | 48 | return &Storage{ 49 | session: conn, 50 | context: ctx, 51 | table: configuration.Table, 52 | }, nil 53 | } 54 | 55 | func (s *Storage) Set(key string, value []byte, expiration time.Duration) error { 56 | if len(key) <= 0 || len(value) <= 0 { 57 | return nil 58 | } 59 | 60 | exp := time.Time{} 61 | if expiration != 0 { 62 | exp = time.Now().Add(expiration).UTC() 63 | } 64 | 65 | return s. 66 | session. 67 | Exec( 68 | s.context, 69 | insertDataString, 70 | driver.Named("table", s.table), 71 | driver.Named("key", key), 72 | driver.Named("value", string(value)), 73 | driver.Named("expiration", exp.Format("2006-01-02 15:04:05")), 74 | ) 75 | } 76 | 77 | func (s *Storage) Get(key string) ([]byte, error) { 78 | if len(key) == 0 { 79 | return []byte{}, nil 80 | } 81 | 82 | var result schema 83 | 84 | row := s.session.QueryRow( 85 | s.context, 86 | selectDataString, 87 | driver.Named("table", s.table), 88 | driver.Named("key", key), 89 | ) 90 | if row.Err() != nil { 91 | return []byte{}, row.Err() 92 | } 93 | 94 | if err := row.ScanStruct(&result); err != nil { 95 | if errors.Is(err, sql.ErrNoRows) { 96 | return []byte{}, nil 97 | } 98 | 99 | return []byte{}, err 100 | } 101 | 102 | // The result.Expiration.IsZero() was returning a false value even when the time was 103 | // set to be the zero value of the time.Time struct (Jan 1st 1970, 00:00:00 UTC) 104 | // so we had to change the comparison 105 | if !time.Unix(0, 0).Equal(result.Expiration) && result.Expiration.Before(time.Now().UTC()) { 106 | return []byte{}, nil 107 | } 108 | 109 | return []byte(result.Value), nil 110 | } 111 | 112 | func (s *Storage) Delete(key string) error { 113 | if len(key) == 0 { 114 | return nil 115 | } 116 | 117 | return s.session.Exec(s.context, deleteDataString, driver.Named("table", s.table), driver.Named("key", key)) 118 | } 119 | 120 | func (s *Storage) Reset() error { 121 | return s.session.Exec(s.context, resetDataString, driver.Named("table", s.table)) 122 | } 123 | 124 | func (s *Storage) Close() error { 125 | return s.session.Close() 126 | } 127 | -------------------------------------------------------------------------------- /cloudflarekv/.gitignore: -------------------------------------------------------------------------------- 1 | index.ts 2 | wrangler.toml 3 | -------------------------------------------------------------------------------- /cloudflarekv/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: cloudflarekv 3 | title: Cloudflare KV 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=cloudflarekv*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-cloudflarekv.yml?label=Tests) 9 | 10 | A Cloudflare KV storage driver using [cloudflare/cloudflare-go](https://github.com/cloudflare/cloudflare-go). 11 | 12 | **Note: Requires Go 1.21 and above** 13 | 14 | ### Table of Contents 15 | 16 | - [Signatures](#signatures) 17 | - [Installation](#installation) 18 | - [Examples](#examples) 19 | - [Config](#config) 20 | - [Default Config](#default-config) 21 | 22 | ### Signatures 23 | 24 | ```go 25 | func New(config ...Config) Storage 26 | func (s *Storage) Get(key string) ([]byte, error) 27 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 28 | func (s *Storage) Delete(key string) error 29 | func (s *Storage) Reset() error 30 | func (s *Storage) Close() error 31 | func (s *Storage) Conn() *cloudflare.API 32 | ``` 33 | 34 | ### Installation 35 | 36 | ```bash 37 | go mod init github.com// 38 | ``` 39 | 40 | And then install the Cloudflare KV implementation: 41 | 42 | ```bash 43 | go get github.com/gofiber/storage/cloudflarekv 44 | ``` 45 | 46 | ### Examples 47 | 48 | Import the storage package. 49 | 50 | ```go 51 | import "github.com/gofiber/storage/cloudflarekv" 52 | ``` 53 | 54 | You can use the following methods to create storage. The Key must be an API Token generated with at least `Account.Workers KV Storage` permission. Check the [Create API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) documentation to generate one. 55 | 56 | ```go 57 | // Initialize default config 58 | store := cloudflarekv.New() 59 | 60 | store := cloudflarekv.New(cloudflarekv.Config{ 61 | Key: "", 62 | Email: "", 63 | AccountID: "fiber", 64 | NamespaceID: "fiber", 65 | Reset: false, 66 | }) 67 | 68 | ``` 69 | 70 | ### Config 71 | 72 | ```go 73 | type Config struct { 74 | 75 | // Cloudflare Auth Token 76 | // 77 | // Optional. Default is "" 78 | Key string 79 | 80 | // Cloudflare Email 81 | // 82 | // Optional. Default is "" 83 | Email string 84 | 85 | // Account id 86 | // 87 | // Optional. Default is "fiber" 88 | AccountID string 89 | 90 | // Namespace id 91 | // 92 | // Optional. Default is "fiber" 93 | NamespaceID string 94 | 95 | // Reset clears any existing keys in existing Table 96 | // 97 | // Optional. Default is false 98 | Reset bool 99 | } 100 | ``` 101 | 102 | ### Default Config 103 | 104 | ```go 105 | var ConfigDefault = Config{ 106 | Key: "", 107 | Email: "", 108 | AccountID: "fiber", 109 | NamespaceID: "fiber", 110 | Reset: false, 111 | } 112 | ``` 113 | -------------------------------------------------------------------------------- /cloudflarekv/config.go: -------------------------------------------------------------------------------- 1 | package cloudflarekv 2 | 3 | // Config defines the config for storage. 4 | type Config struct { 5 | 6 | // Cloudflare Auth Token 7 | // 8 | // Optional. Default is "" 9 | Key string 10 | 11 | // Cloudflare Email 12 | // 13 | // Optional. Default is "" 14 | Email string 15 | 16 | // Account id 17 | // 18 | // Optional. Default is "fiber" 19 | AccountID string 20 | 21 | // Namespace id 22 | // 23 | // Optional. Default is "fiber" 24 | NamespaceID string 25 | 26 | // Reset clears any existing keys in existing Table 27 | // 28 | // Optional. Default is false 29 | Reset bool 30 | } 31 | 32 | // ConfigDefault is the default config 33 | var ConfigDefault = Config{ 34 | Key: "", 35 | Email: "", 36 | AccountID: "fiber", 37 | NamespaceID: "fiber", 38 | Reset: false, 39 | } 40 | 41 | // Helper function to set default values 42 | func configDefault(config ...Config) Config { 43 | // Return default config if nothing provided 44 | if len(config) < 1 { 45 | return ConfigDefault 46 | } 47 | 48 | // Override default config 49 | cfg := config[0] 50 | 51 | // Set default values 52 | if cfg.Key == "" { 53 | cfg.Key = ConfigDefault.Key 54 | } 55 | if cfg.Email == "" { 56 | cfg.Email = ConfigDefault.Email 57 | } 58 | if cfg.AccountID == "" { 59 | cfg.AccountID = ConfigDefault.AccountID 60 | } 61 | if cfg.NamespaceID == "" { 62 | cfg.NamespaceID = ConfigDefault.NamespaceID 63 | } 64 | 65 | return cfg 66 | } 67 | -------------------------------------------------------------------------------- /cloudflarekv/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/cloudflarekv 2 | 3 | go 1.21 4 | 5 | require ( 6 | github.com/cloudflare/cloudflare-go v0.115.0 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/goccy/go-json v0.10.5 // indirect 13 | github.com/google/go-querystring v1.1.0 // indirect 14 | github.com/kr/text v0.2.0 // indirect 15 | github.com/pmezard/go-difflib v1.0.0 // indirect 16 | golang.org/x/net v0.34.0 // indirect 17 | golang.org/x/text v0.21.0 // indirect 18 | golang.org/x/time v0.9.0 // indirect 19 | gopkg.in/yaml.v3 v3.0.1 // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /cloudflarekv/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM= 2 | github.com/cloudflare/cloudflare-go v0.115.0/go.mod h1:Ds6urDwn/TF2uIU24mu7H91xkKP8gSAHxQ44DSZgVmU= 3 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 4 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= 7 | github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= 8 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 9 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 10 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 11 | github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= 12 | github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= 13 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 14 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 15 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 16 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 17 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 18 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 19 | github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= 20 | github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= 21 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 22 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 23 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 24 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 25 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 26 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 27 | golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY= 28 | golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 29 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 30 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 31 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 32 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 33 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 34 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 35 | -------------------------------------------------------------------------------- /coherence/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/coherence 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/oracle/coherence-go-client/v2 v2.2.0 7 | github.com/stretchr/testify v1.10.0 8 | github.com/testcontainers/testcontainers-go v0.37.0 9 | ) 10 | 11 | require ( 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/pmezard/go-difflib v1.0.0 // indirect 14 | google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect 15 | gopkg.in/yaml.v3 v3.0.1 // indirect 16 | ) 17 | 18 | require ( 19 | dario.cat/mergo v1.0.1 // indirect 20 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 21 | github.com/Microsoft/go-winio v0.6.2 // indirect 22 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 23 | github.com/containerd/log v0.1.0 // indirect 24 | github.com/containerd/platforms v0.2.1 // indirect 25 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 26 | github.com/distribution/reference v0.6.0 // indirect 27 | github.com/docker/docker v28.0.1+incompatible // indirect 28 | github.com/docker/go-connections v0.5.0 // indirect 29 | github.com/docker/go-units v0.5.0 // indirect 30 | github.com/ebitengine/purego v0.8.2 // indirect 31 | github.com/felixge/httpsnoop v1.0.4 // indirect 32 | github.com/go-logr/logr v1.4.2 // indirect 33 | github.com/go-logr/stdr v1.2.2 // indirect 34 | github.com/go-ole/go-ole v1.2.6 // indirect 35 | github.com/gogo/protobuf v1.3.2 // indirect 36 | github.com/google/uuid v1.6.0 // indirect 37 | github.com/klauspost/compress v1.17.4 // indirect 38 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 39 | github.com/magiconair/properties v1.8.10 // indirect 40 | github.com/moby/docker-image-spec v1.3.1 // indirect 41 | github.com/moby/patternmatcher v0.6.0 // indirect 42 | github.com/moby/sys/sequential v0.5.0 // indirect 43 | github.com/moby/sys/user v0.1.0 // indirect 44 | github.com/moby/sys/userns v0.1.0 // indirect 45 | github.com/moby/term v0.5.0 // indirect 46 | github.com/morikuni/aec v1.0.0 // indirect 47 | github.com/opencontainers/go-digest v1.0.0 // indirect 48 | github.com/opencontainers/image-spec v1.1.1 // indirect 49 | github.com/pkg/errors v0.9.1 // indirect 50 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 51 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 52 | github.com/sirupsen/logrus v1.9.3 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 60 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 61 | go.opentelemetry.io/otel/sdk v1.35.0 // indirect 62 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 63 | go.opentelemetry.io/proto/otlp v1.6.0 // indirect 64 | golang.org/x/crypto v0.37.0 // indirect 65 | golang.org/x/net v0.39.0 // indirect 66 | golang.org/x/sys v0.32.0 // indirect 67 | golang.org/x/text v0.24.0 // indirect 68 | google.golang.org/grpc v1.72.0 // indirect 69 | google.golang.org/protobuf v1.36.6 // indirect 70 | ) 71 | -------------------------------------------------------------------------------- /couchbase/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: couchbase 3 | title: Couchbase 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=couchbase*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-couchbase.yml?label=Tests) 9 | 10 | A Couchbase storage driver using [couchbase/gocb](https://github.com/couchbase/gocb). 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | - [Signatures](#signatures) 16 | - [Installation](#installation) 17 | - [Examples](#examples) 18 | - [Config](#config) 19 | - [Default Config](#default-config) 20 | 21 | ### Signatures 22 | ```go 23 | func New(config ...Config) Storage 24 | func (s *Storage) Get(key string) ([]byte, error) 25 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 26 | func (s *Storage) Delete(key string) error 27 | func (s *Storage) Reset() error 28 | func (s *Storage) Close() error 29 | func (s *Storage) Conn() *gocb.Cluster 30 | ``` 31 | ### Installation 32 | Couchbase is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 33 | ```bash 34 | go mod init github.com// 35 | ``` 36 | And then install the Couchbase implementation: 37 | ```bash 38 | go get github.com/gofiber/storage/couchbase/v2 39 | ``` 40 | 41 | ### Examples 42 | Import the storage package. 43 | ```go 44 | import "github.com/gofiber/storage/couchbase/v2" 45 | ``` 46 | 47 | You can use the following possibilities to create a storage: 48 | ```go 49 | // Initialize default config 50 | store := couchbase.New() 51 | 52 | // Initialize Couchbase storage with custom config 53 | store := couchbase.New(couchbase.Config{ 54 | Host: "127.0.0.1:8091", 55 | Username: "", 56 | Password: "", 57 | Bucket: 0, 58 | ConnectionTimeout: 3* time.Second, 59 | KVTimeout: 1* time.Second, 60 | }) 61 | ``` 62 | 63 | ### Config 64 | ```go 65 | type Config struct { 66 | // The application username to Connect to the Couchbase cluster 67 | Username string 68 | // The application password to Connect to the Couchbase cluster 69 | Password string 70 | // The connection string for the Couchbase cluster 71 | Host string 72 | // The name of the bucket to Connect to 73 | Bucket string 74 | // The timeout for connecting to the Couchbase cluster 75 | ConnectionTimeout time.Duration 76 | // The timeout for performing operations on the Couchbase cluster 77 | KVTimeout time.Duration 78 | } 79 | ``` 80 | 81 | ### Default Config 82 | ```go 83 | // ConfigDefault is the default config 84 | var ConfigDefault = Config{ 85 | Host: "127.0.0.1:8091", 86 | Username: "admin", 87 | Password: "123456", 88 | Bucket: "fiber_storage", 89 | ConnectionTimeout: 3 * time.Second, 90 | KVTimeout: 1 * time.Second, 91 | } 92 | ``` 93 | -------------------------------------------------------------------------------- /couchbase/config.go: -------------------------------------------------------------------------------- 1 | package couchbase 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Config struct { 8 | // The application username to Connect to the Couchbase cluster 9 | Username string 10 | // The application password to Connect to the Couchbase cluster 11 | Password string 12 | // The connection string for the Couchbase cluster 13 | Host string 14 | // The name of the bucket to Connect to 15 | Bucket string 16 | // The timeout for connecting to the Couchbase cluster 17 | ConnectionTimeout time.Duration 18 | // The timeout for performing operations on the Couchbase cluster 19 | KVTimeout time.Duration 20 | } 21 | 22 | // ConfigDefault is the default config 23 | var ConfigDefault = Config{ 24 | Host: "127.0.0.1:8091", 25 | Username: "admin", 26 | Password: "123456", 27 | Bucket: "fiber_storage", 28 | ConnectionTimeout: 3 * time.Second, 29 | KVTimeout: 1 * time.Second, 30 | } 31 | 32 | func configDefault(config ...Config) Config { 33 | // Return default config if nothing provided 34 | if len(config) < 1 { 35 | return ConfigDefault 36 | } 37 | 38 | // Override default config 39 | cfg := config[0] 40 | 41 | // Set default values 42 | if cfg.Username == "" { 43 | cfg.Username = ConfigDefault.Username 44 | } 45 | if cfg.Password == "" { 46 | cfg.Password = ConfigDefault.Password 47 | } 48 | if cfg.Host == "" { 49 | cfg.Host = ConfigDefault.Host 50 | } 51 | if cfg.Bucket == "" { 52 | cfg.Bucket = ConfigDefault.Bucket 53 | } 54 | if cfg.ConnectionTimeout == 0 { 55 | cfg.ConnectionTimeout = ConfigDefault.ConnectionTimeout 56 | } 57 | if cfg.KVTimeout == 0 { 58 | cfg.KVTimeout = ConfigDefault.KVTimeout 59 | } 60 | 61 | return cfg 62 | } 63 | -------------------------------------------------------------------------------- /couchbase/couchbase.go: -------------------------------------------------------------------------------- 1 | package couchbase 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/couchbase/gocb/v2" 7 | ) 8 | 9 | type Storage struct { 10 | cb *gocb.Cluster 11 | bucket *gocb.Bucket 12 | } 13 | 14 | func New(config ...Config) *Storage { 15 | // Set default config 16 | cfg := configDefault(config...) 17 | 18 | cb, err := gocb.Connect(cfg.Host, gocb.ClusterOptions{ 19 | Authenticator: gocb.PasswordAuthenticator{ 20 | Username: cfg.Username, 21 | Password: cfg.Password, 22 | }, 23 | TimeoutsConfig: gocb.TimeoutsConfig{ 24 | ConnectTimeout: cfg.ConnectionTimeout, 25 | KVTimeout: cfg.KVTimeout, 26 | }, 27 | Transcoder: gocb.NewLegacyTranscoder(), 28 | }) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | _, err = cb.Ping(&gocb.PingOptions{ 34 | Timeout: cfg.ConnectionTimeout, 35 | }) 36 | 37 | if err != nil { 38 | panic(err) 39 | } 40 | 41 | b := cb.Bucket(cfg.Bucket) 42 | 43 | return &Storage{cb: cb, bucket: b} 44 | } 45 | 46 | func (s *Storage) Get(key string) ([]byte, error) { 47 | out, err := s.bucket.DefaultCollection().Get(key, nil) 48 | if err != nil { 49 | switch e := err.(type) { 50 | case *gocb.KeyValueError: 51 | if e.InnerError.Error() == gocb.ErrDocumentNotFound.Error() { 52 | return nil, nil 53 | } 54 | default: //*gocb.TimeoutError,... 55 | return nil, err 56 | } 57 | 58 | return nil, err 59 | } 60 | 61 | var value []byte 62 | if err := out.Content(&value); err != nil { 63 | return nil, err 64 | } 65 | 66 | return value, nil 67 | } 68 | 69 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { 70 | if _, err := s.bucket.DefaultCollection().Upsert(key, val, &gocb.UpsertOptions{ 71 | Expiry: exp, 72 | }); err != nil { 73 | return err 74 | } 75 | 76 | return nil 77 | } 78 | 79 | func (s *Storage) Delete(key string) error { 80 | if _, err := s.bucket.DefaultCollection().Remove(key, nil); err != nil { 81 | return err 82 | } 83 | return nil 84 | } 85 | 86 | func (s *Storage) Reset() error { 87 | return s.cb.Buckets().FlushBucket(s.bucket.Name(), nil) 88 | } 89 | 90 | func (s *Storage) Close() error { 91 | return s.cb.Close(nil) 92 | } 93 | 94 | func (s *Storage) Conn() *gocb.Cluster { 95 | return s.cb 96 | } 97 | -------------------------------------------------------------------------------- /etcd/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: etcd 3 | title: Etcd 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=etcd*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-etcd.yml?label=Tests) 9 | 10 | A Etcd storage driver using [`etcd-io/etcd`](https://github.com/etcd-io/etcd). 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | - [Signatures](#signatures) 16 | - [Installation](#installation) 17 | - [Examples](#examples) 18 | - [Config](#config) 19 | - [Default Config](#default-config) 20 | 21 | ### Signatures 22 | ```go 23 | func New(config ...Config) *Storage 24 | func (s *Storage) Get(key string) ([]byte, error) 25 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 26 | func (s *Storage) Delete(key string) error 27 | func (s *Storage) Reset() error 28 | func (s *Storage) Close() error 29 | func (s *Storage) Conn() *clientv3.Client 30 | ``` 31 | 32 | ### Installation 33 | Etcd is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 34 | ```bash 35 | go mod init github.com// 36 | ``` 37 | And then install the etcd implementation: 38 | ```bash 39 | go get github.com/gofiber/storage/etcd/v2 40 | ``` 41 | 42 | ### Examples 43 | Import the storage package. 44 | ```go 45 | import "github.com/gofiber/storage/etcd/v2" 46 | ``` 47 | 48 | You can use the following possibilities to create a storage: 49 | ```go 50 | // Initialize default config 51 | store := etcd.New() 52 | 53 | // Initialize custom config 54 | store := etcd.New(Config{ 55 | Endpoints: []string{"localhost:2379"}, 56 | }) 57 | 58 | ``` 59 | 60 | ### Config 61 | ```go 62 | type Config struct { 63 | // Endpoints is a list of URLs. 64 | Endpoints []string 65 | // DialTimeout is the timeout for failing to establish a connection. 66 | DialTimeout time.Duration 67 | // Username is a username for authentication. 68 | Username string 69 | // Password is a password for authentication. 70 | Password string 71 | // TLS holds the client secure credentials, if any. 72 | TLS *tls.Config 73 | } 74 | ``` 75 | 76 | ### Default Config 77 | ```go 78 | var ConfigDefault = Config{ 79 | Endpoints: []string{"localhost:2379"}, 80 | DialTimeout: 2 * time.Second, 81 | Username: "", 82 | Password: "", 83 | TLS: nil, 84 | } 85 | ``` 86 | -------------------------------------------------------------------------------- /etcd/config.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "crypto/tls" 5 | "time" 6 | ) 7 | 8 | // Config defines the config for storage. 9 | type Config struct { 10 | // Endpoints is a list of URLs. 11 | Endpoints []string 12 | // DialTimeout is the timeout for failing to establish a connection. 13 | DialTimeout time.Duration 14 | // Username is a username for authentication. 15 | Username string 16 | // Password is a password for authentication. 17 | Password string 18 | // TLS holds the client secure credentials, if any. 19 | TLS *tls.Config 20 | } 21 | 22 | // ConfigDefault is the default config 23 | var ConfigDefault = Config{ 24 | Endpoints: []string{"localhost:2379"}, 25 | DialTimeout: 2 * time.Second, 26 | Username: "", 27 | Password: "", 28 | TLS: nil, 29 | } 30 | 31 | // Helper function to set default values 32 | func configDefault(config ...Config) Config { 33 | // Return default config if nothing provided 34 | if len(config) < 1 { 35 | return ConfigDefault 36 | } 37 | 38 | // Override default config 39 | cfg := config[0] 40 | // Set default values 41 | if cfg.Username == "" { 42 | cfg.Username = ConfigDefault.Username 43 | } 44 | if cfg.Password == "" { 45 | cfg.Password = ConfigDefault.Password 46 | } 47 | if cfg.DialTimeout == 0 { 48 | cfg.DialTimeout = ConfigDefault.DialTimeout 49 | } 50 | 51 | return cfg 52 | } 53 | -------------------------------------------------------------------------------- /etcd/etcd.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "go.etcd.io/etcd/client/v3" 8 | ) 9 | 10 | type Storage struct { 11 | db *clientv3.Client 12 | } 13 | 14 | func New(config ...Config) *Storage { 15 | cfg := configDefault(config...) 16 | 17 | cli, err := clientv3.New(clientv3.Config{ 18 | Endpoints: cfg.Endpoints, 19 | DialTimeout: cfg.DialTimeout, 20 | Username: cfg.Username, 21 | Password: cfg.Password, 22 | TLS: cfg.TLS, 23 | }) 24 | if err != nil { 25 | panic(err) 26 | } 27 | 28 | store := &Storage{ 29 | db: cli, 30 | } 31 | 32 | return store 33 | } 34 | 35 | func (s *Storage) Get(key string) ([]byte, error) { 36 | if len(key) <= 0 { 37 | return nil, nil 38 | } 39 | item, err := s.db.Get(context.Background(), key) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | if len(item.Kvs) <= 0 { 45 | return nil, nil 46 | } 47 | 48 | return item.Kvs[0].Value, nil 49 | } 50 | 51 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { 52 | // Ain't Nobody Got Time For That 53 | if len(key) <= 0 || len(val) <= 0 { 54 | return nil 55 | } 56 | 57 | lease, err := s.db.Grant(context.Background(), int64(exp.Seconds())) 58 | if err != nil { 59 | return err 60 | } 61 | 62 | _, err = s.db.Put(context.Background(), key, string(val), clientv3.WithLease(lease.ID)) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | return nil 68 | } 69 | 70 | func (s *Storage) Delete(key string) error { 71 | if len(key) <= 0 { 72 | return nil 73 | } 74 | 75 | _, err := s.db.Delete(context.Background(), key) 76 | if err != nil { 77 | return err 78 | } 79 | 80 | return nil 81 | } 82 | 83 | func (s *Storage) Reset() error { 84 | _, err := s.db.Delete(context.Background(), "", clientv3.WithPrefix()) 85 | if err != nil { 86 | return err 87 | } 88 | 89 | return nil 90 | } 91 | 92 | func (s *Storage) Close() error { 93 | return s.db.Close() 94 | } 95 | 96 | func (s *Storage) Conn() *clientv3.Client { 97 | return s.db 98 | } 99 | -------------------------------------------------------------------------------- /etcd/etcd_test.go: -------------------------------------------------------------------------------- 1 | package etcd 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | var testStore *Storage 12 | 13 | func TestMain(m *testing.M) { 14 | testStore = New(Config{ 15 | Endpoints: []string{"localhost:2379"}, 16 | }) 17 | 18 | code := m.Run() 19 | 20 | _ = testStore.Reset() 21 | _ = testStore.Close() 22 | os.Exit(code) 23 | } 24 | 25 | func TestSetEtcd_ShouldReturnNoError(t *testing.T) { 26 | var ( 27 | key = "john" 28 | val = []byte("doe") 29 | ) 30 | 31 | err := testStore.Set(key, val, 0) 32 | require.NoError(t, err) 33 | } 34 | 35 | func TestGetEtcd_ShouldReturnNil_WhenDocumentNotFound(t *testing.T) { 36 | val, err := testStore.Get("not_found_key") 37 | 38 | require.NoError(t, err) 39 | require.Zero(t, len(val)) 40 | } 41 | 42 | func TestSetAndGet_GetShouldReturn_SettedValueWithoutError(t *testing.T) { 43 | err := testStore.Set("test", []byte("fiber_test_value"), 0) 44 | require.NoError(t, err) 45 | 46 | val, err := testStore.Get("test") 47 | 48 | require.NoError(t, err) 49 | require.Equal(t, val, []byte("fiber_test_value")) 50 | } 51 | 52 | func TestSetAndGet_GetShouldReturnNil_WhenTTLExpired(t *testing.T) { 53 | err := testStore.Set("test", []byte("fiber_test_value"), 3*time.Second) 54 | require.NoError(t, err) 55 | 56 | time.Sleep(6 * time.Second) 57 | 58 | val, err := testStore.Get("test") 59 | 60 | require.NoError(t, err) 61 | require.Zero(t, len(val)) 62 | } 63 | 64 | func TestSetAndDelete_DeleteShouldReturn_NoError(t *testing.T) { 65 | err := testStore.Set("test", []byte("fiber_test_value"), 0) 66 | require.NoError(t, err) 67 | 68 | err = testStore.Delete("test") 69 | require.NoError(t, err) 70 | 71 | _, err = testStore.Get("test") 72 | require.NoError(t, err) 73 | } 74 | 75 | func TestSetAndReset_ResetShouldReturn_NoError(t *testing.T) { 76 | err := testStore.Set("test", []byte("fiber_test_value"), 0) 77 | require.NoError(t, err) 78 | 79 | err = testStore.Reset() 80 | require.NoError(t, err) 81 | 82 | _, err = testStore.Get("test") 83 | require.NoError(t, err) 84 | } 85 | 86 | func TestClose_CloseShouldReturn_NoError(t *testing.T) { 87 | err := testStore.Close() 88 | require.NoError(t, err) 89 | } 90 | 91 | func TestGetConn_ReturnsNotNill(t *testing.T) { 92 | require.True(t, testStore.Conn() != nil) 93 | } 94 | 95 | func Benchmark_Etcd_Set(b *testing.B) { 96 | b.ReportAllocs() 97 | b.ResetTimer() 98 | 99 | var err error 100 | for i := 0; i < b.N; i++ { 101 | err = testStore.Set("john", []byte("doe"), 0) 102 | } 103 | 104 | require.NoError(b, err) 105 | } 106 | 107 | func Benchmark_Etcd_Get(b *testing.B) { 108 | err := testStore.Set("john", []byte("doe"), 0) 109 | require.NoError(b, err) 110 | 111 | b.ReportAllocs() 112 | b.ResetTimer() 113 | 114 | for i := 0; i < b.N; i++ { 115 | _, err = testStore.Get("john") 116 | } 117 | 118 | require.NoError(b, err) 119 | } 120 | 121 | func Benchmark_Etcd_SetAndDelete(b *testing.B) { 122 | b.ReportAllocs() 123 | b.ResetTimer() 124 | 125 | var err error 126 | for i := 0; i < b.N; i++ { 127 | _ = testStore.Set("john", []byte("doe"), 0) 128 | err = testStore.Delete("john") 129 | } 130 | 131 | require.NoError(b, err) 132 | } 133 | -------------------------------------------------------------------------------- /etcd/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/etcd/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/stretchr/testify v1.10.0 7 | go.etcd.io/etcd/client/v3 v3.5.12 8 | ) 9 | 10 | require ( 11 | github.com/coreos/go-semver v0.3.1 // indirect 12 | github.com/coreos/go-systemd/v22 v22.5.0 // indirect 13 | github.com/davecgh/go-spew v1.1.1 // indirect 14 | github.com/gogo/protobuf v1.3.2 // indirect 15 | github.com/golang/protobuf v1.5.3 // indirect 16 | github.com/pmezard/go-difflib v1.0.0 // indirect 17 | go.etcd.io/etcd/api/v3 v3.5.12 // indirect 18 | go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect 19 | go.uber.org/multierr v1.11.0 // indirect 20 | go.uber.org/zap v1.25.0 // indirect 21 | golang.org/x/net v0.23.0 // indirect 22 | golang.org/x/sys v0.18.0 // indirect 23 | golang.org/x/text v0.14.0 // indirect 24 | google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect 25 | google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect 26 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect 27 | google.golang.org/grpc v1.59.0 // indirect 28 | google.golang.org/protobuf v1.33.0 // indirect 29 | gopkg.in/yaml.v3 v3.0.1 // indirect 30 | ) 31 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage 2 | 3 | go 1.19 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofiber/storage/087d3e71d7181b9e6db4039be621cc982be0faa5/go.sum -------------------------------------------------------------------------------- /go.work: -------------------------------------------------------------------------------- 1 | go 1.23.0 2 | 3 | use ( 4 | . 5 | ./aerospike 6 | ./arangodb 7 | ./azureblob 8 | ./badger 9 | ./bbolt 10 | ./cassandra 11 | ./clickhouse 12 | ./cloudflarekv 13 | ./coherence 14 | ./couchbase 15 | ./dynamodb 16 | ./etcd 17 | ./leveldb 18 | ./memcache 19 | ./memory 20 | ./minio 21 | ./mockstorage 22 | ./mongodb 23 | ./mssql 24 | ./mysql 25 | ./nats 26 | ./neo4j 27 | ./pebble 28 | ./postgres 29 | ./redis 30 | ./ristretto 31 | ./rueidis 32 | ./s3 33 | ./scylladb 34 | ./sqlite3 35 | ./surrealdb 36 | ./testhelpers/redis 37 | ./valkey 38 | ) 39 | -------------------------------------------------------------------------------- /leveldb/config_test.go: -------------------------------------------------------------------------------- 1 | package leveldb 2 | 3 | import ( 4 | "runtime" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func TestConfigConfigMaxOpenFiles(t *testing.T) { 11 | cfg := Config{ 12 | MaxOpenFiles: 1000, 13 | } 14 | require.Equal(t, 1000, cfg.MaxOpenFiles) 15 | } 16 | 17 | func TestConfigDefaultDarwin(t *testing.T) { // MacOS 18 | cfg := configDefault() 19 | if runtime.GOOS == "darwin" { 20 | require.Equal(t, 200, cfg.MaxOpenFiles) 21 | } else { 22 | require.Equal(t, 500, cfg.MaxOpenFiles) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /leveldb/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/leveldb 2 | 3 | go 1.23 4 | 5 | require ( 6 | github.com/stretchr/testify v1.10.0 7 | github.com/syndtr/goleveldb v1.0.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/golang/snappy v1.0.0 // indirect 13 | github.com/pmezard/go-difflib v1.0.0 // indirect 14 | gopkg.in/yaml.v3 v3.0.1 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /memcache/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: memcache 3 | title: Memcache 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=memcache*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-memcache.yml?label=Tests) 9 | 10 | A Memcache storage driver using [`bradfitz/gomemcache`](https://github.com/bradfitz/gomemcache). 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | - [Signatures](#signatures) 16 | - [Installation](#installation) 17 | - [Examples](#examples) 18 | - [Config](#config) 19 | - [Default Config](#default-config) 20 | 21 | ### Signatures 22 | ```go 23 | func New(config ...Config) Storage 24 | func (s *Storage) Get(key string) ([]byte, error) 25 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 26 | func (s *Storage) Delete(key string) error 27 | func (s *Storage) Reset() error 28 | func (s *Storage) Close() error 29 | func (s *Storage) Conn() *mc.Client 30 | ``` 31 | 32 | ### Installation 33 | Memory is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 34 | ```bash 35 | go mod init github.com// 36 | ``` 37 | And then install the memory implementation: 38 | ```bash 39 | go get github.com/gofiber/storage/memory/v2 40 | ``` 41 | 42 | ### Examples 43 | Import the storage package. 44 | ```go 45 | import "github.com/gofiber/storage/memcache" 46 | ``` 47 | 48 | You can use the following possibilities to create a storage: 49 | ```go 50 | // Initialize default config 51 | store := memcache.New() 52 | 53 | // Initialize custom config 54 | store := memcache.New(memcache.Config{ 55 | Servers: "localhost:11211", 56 | }) 57 | ``` 58 | 59 | ### Config 60 | ```go 61 | type Config struct { 62 | // Server list divided by , 63 | // i.e. server1:11211, server2:11212 64 | // 65 | // Optional. Default is "127.0.0.1:11211" 66 | Servers string 67 | 68 | // Reset clears any existing keys in existing Table 69 | // 70 | // Optional. Default is false 71 | Reset bool 72 | } 73 | ``` 74 | 75 | ### Default Config 76 | ```go 77 | var ConfigDefault = Config{ 78 | Servers: "127.0.0.1:11211", 79 | } 80 | ``` 81 | -------------------------------------------------------------------------------- /memcache/config.go: -------------------------------------------------------------------------------- 1 | package memcache 2 | 3 | import "time" 4 | 5 | // Config defines the config for storage. 6 | type Config struct { 7 | // Server list divided by , 8 | // i.e. server1:11211, server2:11212 9 | // 10 | // Optional. Default is "127.0.0.1:11211" 11 | Servers string 12 | 13 | // Reset clears any existing keys in existing Table 14 | // 15 | // Optional. Default is false 16 | Reset bool 17 | 18 | // The socket read/write timeout. 19 | // 20 | // Optional. Default is 100 * time.Millisecond 21 | timeout time.Duration 22 | 23 | // The maximum number of idle connections that will be maintained per address. 24 | // 25 | // Consider your expected traffic rates and latency carefully. This should 26 | // be set to a number higher than your peak parallel requests. 27 | // 28 | // Optional. Default is 2 29 | maxIdleConns int 30 | } 31 | 32 | // ConfigDefault is the default config 33 | var ConfigDefault = Config{ 34 | Servers: "127.0.0.1:11211", 35 | timeout: 100 * time.Millisecond, 36 | maxIdleConns: 2, 37 | } 38 | 39 | // Helper function to set default values 40 | func configDefault(config ...Config) Config { 41 | // Return default config if nothing provided 42 | if len(config) < 1 { 43 | return ConfigDefault 44 | } 45 | 46 | // Override default config 47 | cfg := config[0] 48 | 49 | // Set default values 50 | if len(cfg.Servers) < 1 { 51 | cfg.Servers = ConfigDefault.Servers 52 | } 53 | 54 | return cfg 55 | } 56 | -------------------------------------------------------------------------------- /memcache/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/memcache/v2 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.24.1 6 | 7 | require ( 8 | github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf 9 | github.com/stretchr/testify v1.10.0 10 | github.com/testcontainers/testcontainers-go v0.37.0 11 | ) 12 | 13 | require ( 14 | dario.cat/mergo v1.0.1 // indirect 15 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 16 | github.com/Microsoft/go-winio v0.6.2 // indirect 17 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/distribution/reference v0.6.0 // indirect 23 | github.com/docker/docker v28.0.1+incompatible // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/ebitengine/purego v0.8.2 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-logr/logr v1.4.2 // indirect 29 | github.com/go-logr/stdr v1.2.2 // indirect 30 | github.com/go-ole/go-ole v1.2.6 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/klauspost/compress v1.17.4 // indirect 34 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 35 | github.com/magiconair/properties v1.8.10 // indirect 36 | github.com/moby/docker-image-spec v1.3.1 // indirect 37 | github.com/moby/patternmatcher v0.6.0 // indirect 38 | github.com/moby/sys/sequential v0.5.0 // indirect 39 | github.com/moby/sys/user v0.1.0 // indirect 40 | github.com/moby/sys/userns v0.1.0 // indirect 41 | github.com/moby/term v0.5.0 // indirect 42 | github.com/morikuni/aec v1.0.0 // indirect 43 | github.com/opencontainers/go-digest v1.0.0 // indirect 44 | github.com/opencontainers/image-spec v1.1.1 // indirect 45 | github.com/pkg/errors v0.9.1 // indirect 46 | github.com/pmezard/go-difflib v1.0.0 // indirect 47 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 48 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 49 | github.com/sirupsen/logrus v1.9.3 // indirect 50 | github.com/tklauser/go-sysconf v0.3.12 // indirect 51 | github.com/tklauser/numcpus v0.6.1 // indirect 52 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 53 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 54 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 55 | go.opentelemetry.io/otel v1.35.0 // indirect 56 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 57 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 58 | go.opentelemetry.io/otel/sdk v1.35.0 // indirect 59 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 60 | go.opentelemetry.io/proto/otlp v1.6.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sys v0.32.0 // indirect 63 | google.golang.org/protobuf v1.36.6 // indirect 64 | gopkg.in/yaml.v3 v3.0.1 // indirect 65 | ) 66 | -------------------------------------------------------------------------------- /memcache/memcache.go: -------------------------------------------------------------------------------- 1 | package memcache 2 | 3 | import ( 4 | "strings" 5 | "sync" 6 | "time" 7 | 8 | mc "github.com/bradfitz/gomemcache/memcache" 9 | ) 10 | 11 | // Storage interface that is implemented by storage providers 12 | type Storage struct { 13 | db *mc.Client 14 | items *sync.Pool 15 | } 16 | 17 | // New creates a new storage 18 | func New(config ...Config) *Storage { 19 | // Set default config 20 | cfg := configDefault(config...) 21 | 22 | // Split comma separated servers into slice 23 | serverList := strings.Split(strings.TrimSpace(cfg.Servers), ",") 24 | 25 | // Create db 26 | db := mc.New(serverList...) 27 | 28 | // Set options 29 | db.Timeout = cfg.timeout 30 | db.MaxIdleConns = cfg.maxIdleConns 31 | 32 | // Ping database to ensure a connection has been made 33 | if err := db.Ping(); err != nil { 34 | panic(err) 35 | } 36 | 37 | if cfg.Reset { 38 | if err := db.DeleteAll(); err != nil { 39 | panic(err) 40 | } 41 | } 42 | 43 | // Create storage 44 | store := &Storage{ 45 | db: db, 46 | items: &sync.Pool{ 47 | New: func() interface{} { 48 | return new(mc.Item) 49 | }, 50 | }, 51 | } 52 | 53 | return store 54 | } 55 | 56 | // Get value by key 57 | func (s *Storage) Get(key string) ([]byte, error) { 58 | if len(key) <= 0 { 59 | return nil, nil 60 | } 61 | item, err := s.db.Get(key) 62 | if err == mc.ErrCacheMiss { 63 | return nil, nil 64 | } else if err != nil { 65 | return nil, err 66 | } 67 | 68 | return item.Value, nil 69 | } 70 | 71 | // Set key with value 72 | // Set key with value 73 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { 74 | // Ain't Nobody Got Time For That 75 | if len(key) <= 0 || len(val) <= 0 { 76 | return nil 77 | } 78 | item := s.acquireItem() 79 | item.Key = key 80 | item.Value = val 81 | item.Expiration = int32(exp.Seconds()) 82 | 83 | err := s.db.Set(item) 84 | 85 | s.releaseItem(item) 86 | 87 | return err 88 | } 89 | 90 | // Delete key by key 91 | func (s *Storage) Delete(key string) error { 92 | // Ain't Nobody Got Time For That 93 | if len(key) <= 0 { 94 | return nil 95 | } 96 | return s.db.Delete(key) 97 | } 98 | 99 | // Reset all keys 100 | func (s *Storage) Reset() error { 101 | return s.db.DeleteAll() 102 | } 103 | 104 | // Close the database 105 | func (s *Storage) Close() error { 106 | return nil 107 | } 108 | 109 | // Acquire item from pool 110 | func (s *Storage) acquireItem() *mc.Item { 111 | return s.items.Get().(*mc.Item) 112 | } 113 | 114 | // Release item from pool 115 | func (s *Storage) releaseItem(item *mc.Item) { 116 | if item != nil { 117 | item.Key = "" 118 | item.Value = nil 119 | item.Expiration = 0 120 | 121 | s.items.Put(item) 122 | } 123 | } 124 | 125 | // Return database client 126 | func (s *Storage) Conn() *mc.Client { 127 | return s.db 128 | } 129 | -------------------------------------------------------------------------------- /memory/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: memory 3 | title: Memory 4 | --- 5 | 6 | 7 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=memory*) 8 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 9 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-memory.yml?label=Tests) 10 | 11 | An in-memory storage driver. 12 | 13 | **Note: Requires Go 1.19 and above** 14 | 15 | ### Table of Contents 16 | - [Signatures](#signatures) 17 | - [Installation](#installation) 18 | - [Examples](#examples) 19 | - [Config](#config) 20 | - [Default Config](#default-config) 21 | 22 | 23 | ### Signatures 24 | ```go 25 | func New(config ...Config) Storage 26 | func (s *Storage) Get(key string) ([]byte, error) 27 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 28 | func (s *Storage) Delete(key string) error 29 | func (s *Storage) Reset() error 30 | func (s *Storage) Close() error 31 | func (s *Storage) Conn() map[string]entry 32 | func (s *Storage) Keys() ([][]byte, error) 33 | ``` 34 | 35 | ### Installation 36 | Memory is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 37 | ```bash 38 | go mod init github.com// 39 | ``` 40 | And then install the memory implementation: 41 | ```bash 42 | go get github.com/gofiber/storage/memory/v2 43 | ``` 44 | 45 | ### Examples 46 | Import the storage package. 47 | ```go 48 | import "github.com/gofiber/storage/memory/v2" 49 | ``` 50 | 51 | You can use the following possibilities to create a storage: 52 | ```go 53 | // Initialize default config 54 | store := memory.New() 55 | 56 | // Initialize custom config 57 | store := memory.New(memory.Config{ 58 | GCInterval: 10 * time.Second, 59 | }) 60 | ``` 61 | 62 | ### Config 63 | ```go 64 | type Config struct { 65 | // Time before deleting expired keys 66 | // 67 | // Default is 10 * time.Second 68 | GCInterval time.Duration 69 | } 70 | ``` 71 | 72 | ### Default Config 73 | ```go 74 | var ConfigDefault = Config{ 75 | GCInterval: 10 * time.Second, 76 | } 77 | ``` 78 | -------------------------------------------------------------------------------- /memory/config.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import "time" 4 | 5 | // Config defines the config for storage. 6 | type Config struct { 7 | // Time before deleting expired keys 8 | // 9 | // Default is 10 * time.Second 10 | GCInterval time.Duration 11 | } 12 | 13 | // ConfigDefault is the default config 14 | var ConfigDefault = Config{ 15 | GCInterval: 10 * time.Second, 16 | } 17 | 18 | // configDefault is a helper function to set default values 19 | func configDefault(config ...Config) Config { 20 | // Return default config if nothing provided 21 | if len(config) < 1 { 22 | return ConfigDefault 23 | } 24 | 25 | // Override default config 26 | cfg := config[0] 27 | 28 | // Set default values 29 | if int(cfg.GCInterval.Seconds()) <= 0 { 30 | cfg.GCInterval = ConfigDefault.GCInterval 31 | } 32 | return cfg 33 | } 34 | -------------------------------------------------------------------------------- /memory/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/memory/v2 2 | 3 | go 1.19 4 | 5 | require github.com/stretchr/testify v1.10.0 6 | 7 | require ( 8 | github.com/davecgh/go-spew v1.1.1 // indirect 9 | github.com/pmezard/go-difflib v1.0.0 // indirect 10 | gopkg.in/yaml.v3 v3.0.1 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /memory/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 4 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 5 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 6 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 7 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 8 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 9 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 10 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 11 | -------------------------------------------------------------------------------- /memory/internal/time.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "sync" 5 | "sync/atomic" 6 | "time" 7 | ) 8 | 9 | var ( 10 | timestampTimer sync.Once 11 | // Timestamp please start the timer function before you use this value 12 | // please load the value with atomic `atomic.LoadUint32(&utils.Timestamp)` 13 | Timestamp uint32 14 | ) 15 | 16 | // StartTimeStampUpdater starts a concurrent function which stores the timestamp to an atomic value per second, 17 | // which is much better for performance than determining it at runtime each time 18 | func StartTimeStampUpdater() { 19 | timestampTimer.Do(func() { 20 | // set initial value 21 | atomic.StoreUint32(&Timestamp, uint32(time.Now().Unix())) 22 | go func(sleep time.Duration) { 23 | ticker := time.NewTicker(sleep) 24 | defer ticker.Stop() 25 | 26 | for t := range ticker.C { 27 | // update timestamp 28 | atomic.StoreUint32(&Timestamp, uint32(t.Unix())) 29 | } 30 | }(1 * time.Second) // duration 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /memory/internal/time_test.go: -------------------------------------------------------------------------------- 1 | package internal 2 | 3 | import ( 4 | "sync/atomic" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func checkTimeStamp(t testing.TB, expectedCurrent, actualCurrent uint32) { 12 | // test with some buffer in front and back of the expectedCurrent time -> because of the timing on the work machine 13 | require.True(t, actualCurrent >= expectedCurrent-1 || actualCurrent <= expectedCurrent+1) 14 | } 15 | 16 | func Test_TimeStampUpdater(t *testing.T) { 17 | t.Parallel() 18 | 19 | StartTimeStampUpdater() 20 | 21 | now := uint32(time.Now().Unix()) 22 | checkTimeStamp(t, now, atomic.LoadUint32(&Timestamp)) 23 | // one second later 24 | time.Sleep(1 * time.Second) 25 | checkTimeStamp(t, now+1, atomic.LoadUint32(&Timestamp)) 26 | // two seconds later 27 | time.Sleep(1 * time.Second) 28 | checkTimeStamp(t, now+2, atomic.LoadUint32(&Timestamp)) 29 | } 30 | 31 | func Benchmark_CalculateTimestamp(b *testing.B) { 32 | StartTimeStampUpdater() 33 | 34 | var res uint32 35 | b.Run("fiber", func(b *testing.B) { 36 | for n := 0; n < b.N; n++ { 37 | res = atomic.LoadUint32(&Timestamp) 38 | } 39 | checkTimeStamp(b, uint32(time.Now().Unix()), res) 40 | }) 41 | b.Run("default", func(b *testing.B) { 42 | for n := 0; n < b.N; n++ { 43 | res = uint32(time.Now().Unix()) 44 | } 45 | checkTimeStamp(b, uint32(time.Now().Unix()), res) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /minio/config.go: -------------------------------------------------------------------------------- 1 | package minio 2 | 3 | import ( 4 | "github.com/minio/minio-go/v7" 5 | ) 6 | 7 | // Config defines the config for storage. 8 | type Config struct { 9 | // Bucket 10 | // Default fiber-bucket 11 | Bucket string 12 | 13 | // Endpoint is a host name or an IP address 14 | Endpoint string 15 | 16 | // Region Set this value to override region cache 17 | // Optional 18 | Region string 19 | 20 | // Token Set this value to provide x-amz-security-token (AWS S3 specific) 21 | // Optional, Default is false 22 | Token string 23 | 24 | // Secure If set to true, https is used instead of http. 25 | // Default is false 26 | Secure bool 27 | 28 | // Reset clears any existing keys in existing Bucket 29 | // Optional. Default is false 30 | Reset bool 31 | 32 | // The maximum number of times requests that encounter retryable failures should be attempted. 33 | // Optional. Default is 10, same as the MinIO client. 34 | MaxRetry int 35 | 36 | // Credentials Minio access key and Minio secret key. 37 | // Need to be defined 38 | Credentials Credentials 39 | 40 | // GetObjectOptions Options for GET requests specifying additional options like encryption, If-Match 41 | GetObjectOptions minio.GetObjectOptions 42 | 43 | // PutObjectOptions 44 | // Allows user to set optional custom metadata, content headers, encryption keys and number of threads for multipart upload operation. 45 | PutObjectOptions minio.PutObjectOptions 46 | 47 | // ListObjectsOptions Options per to list objects 48 | ListObjectsOptions minio.ListObjectsOptions 49 | 50 | // RemoveObjectOptions Allows user to set options 51 | RemoveObjectOptions minio.RemoveObjectOptions 52 | } 53 | 54 | type Credentials struct { 55 | // AccessKeyID is like user-id that uniquely identifies your account. 56 | AccessKeyID string 57 | // SecretAccessKey is the password to your account. 58 | SecretAccessKey string 59 | } 60 | 61 | // ConfigDefault is the default config 62 | var ConfigDefault = Config{ 63 | Bucket: "fiber-bucket", 64 | Endpoint: "", 65 | Region: "", 66 | Token: "", 67 | Secure: false, 68 | Reset: false, 69 | MaxRetry: minio.MaxRetry, 70 | Credentials: Credentials{}, 71 | GetObjectOptions: minio.GetObjectOptions{}, 72 | PutObjectOptions: minio.PutObjectOptions{}, 73 | ListObjectsOptions: minio.ListObjectsOptions{}, 74 | RemoveObjectOptions: minio.RemoveObjectOptions{}, 75 | } 76 | 77 | // Helper function to set default values 78 | func configDefault(config ...Config) Config { 79 | // Return default config if nothing provided 80 | if len(config) < 1 { 81 | return ConfigDefault 82 | } 83 | 84 | // Override default config 85 | cfg := config[0] 86 | 87 | // Set default values 88 | if cfg.Bucket == "" { 89 | cfg.Bucket = ConfigDefault.Bucket 90 | } 91 | 92 | if cfg.MaxRetry < 1 { 93 | cfg.MaxRetry = ConfigDefault.MaxRetry 94 | } 95 | 96 | return cfg 97 | } 98 | -------------------------------------------------------------------------------- /mockstorage/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/mockstorage 2 | 3 | go 1.21 4 | -------------------------------------------------------------------------------- /mockstorage/go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofiber/storage/087d3e71d7181b9e6db4039be621cc982be0faa5/mockstorage/go.sum -------------------------------------------------------------------------------- /mongodb/config.go: -------------------------------------------------------------------------------- 1 | package mongodb 2 | 3 | // Config defines the config for storage. 4 | type Config struct { 5 | // Connection string to use for DB. Will override all other authentication values if used 6 | // 7 | // Optional. Default is "" 8 | ConnectionURI string 9 | 10 | // Host name where the DB is hosted 11 | // 12 | // Optional. Default is "127.0.0.1" 13 | Host string 14 | 15 | // Port where the DB is listening on 16 | // 17 | // Optional. Default is 27017 18 | Port int 19 | 20 | // Server username 21 | // 22 | // Optional. Default is "" 23 | Username string 24 | 25 | // Server password 26 | // 27 | // Optional. Default is "" 28 | Password string 29 | 30 | // Database name 31 | // 32 | // Optional. Default is "fiber" 33 | Database string 34 | 35 | // Collection name 36 | // 37 | // Optional. Default is "fiber_storage" 38 | Collection string 39 | 40 | // Reset clears any existing keys in existing Table 41 | // 42 | // Optional. Default is false 43 | Reset bool 44 | } 45 | 46 | // ConfigDefault is the default config 47 | var ConfigDefault = Config{ 48 | ConnectionURI: "", 49 | Host: "127.0.0.1", 50 | Port: 27017, 51 | Database: "fiber", 52 | Collection: "fiber_storage", 53 | Reset: false, 54 | } 55 | 56 | // Helper function to set default values 57 | func configDefault(config ...Config) Config { 58 | // Return default config if nothing provided 59 | if len(config) < 1 { 60 | return ConfigDefault 61 | } 62 | 63 | // Override default config 64 | cfg := config[0] 65 | 66 | // Set default values 67 | if cfg.Host == "" { 68 | cfg.Host = ConfigDefault.Host 69 | } 70 | if cfg.Port <= 0 { 71 | cfg.Port = ConfigDefault.Port 72 | } 73 | if cfg.Database == "" { 74 | cfg.Database = ConfigDefault.Database 75 | } 76 | if cfg.Collection == "" { 77 | cfg.Collection = ConfigDefault.Collection 78 | } 79 | return cfg 80 | } 81 | -------------------------------------------------------------------------------- /mssql/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/mssql/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/microsoft/go-mssqldb v1.8.1 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect 13 | github.com/golang-sql/sqlexp v0.1.0 // indirect 14 | github.com/google/uuid v1.6.0 // indirect 15 | github.com/pmezard/go-difflib v1.0.0 // indirect 16 | golang.org/x/crypto v0.24.0 // indirect 17 | golang.org/x/text v0.16.0 // indirect 18 | gopkg.in/yaml.v3 v3.0.1 // indirect 19 | ) 20 | -------------------------------------------------------------------------------- /mssql/go.sum: -------------------------------------------------------------------------------- 1 | github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= 2 | github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= 3 | github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= 4 | github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw= 5 | github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= 6 | github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= 7 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 8 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= 10 | github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= 11 | github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 12 | github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= 13 | github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= 14 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 15 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 16 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 17 | github.com/microsoft/go-mssqldb v1.8.1 h1:/LPVjSb992vTa8CMVvliTMT//UAKj/jpe1xb/jJBjIk= 18 | github.com/microsoft/go-mssqldb v1.8.1/go.mod h1:vp38dT33FGfVotRiTmDo3bFyaHq+p3LektQrjTULowo= 19 | github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= 20 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 21 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 22 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 23 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 24 | golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= 25 | golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= 26 | golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= 27 | golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= 28 | golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= 29 | golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 30 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 31 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 32 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 33 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 34 | -------------------------------------------------------------------------------- /mysql/config.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | // Config defines the config for storage. 10 | type Config struct { 11 | // DB Will override ConnectionURI and all other authentication values if used 12 | // 13 | // Optional. Default is nil 14 | Db *sql.DB 15 | 16 | // Connection string to use for DB. Will override all other authentication values if used 17 | // 18 | // Optional. Default is "" 19 | ConnectionURI string 20 | 21 | // Host name where the DB is hosted 22 | // 23 | // Optional. Default is "127.0.0.1" 24 | Host string 25 | 26 | // Port where the DB is listening on 27 | // 28 | // Optional. Default is 3306 29 | Port int 30 | 31 | // Server username 32 | // 33 | // Optional. Default is "" 34 | Username string 35 | 36 | // Server password 37 | // 38 | // Optional. Default is "" 39 | Password string 40 | 41 | // Database name 42 | // 43 | // Optional. Default is "fiber" 44 | Database string 45 | 46 | // Table name 47 | // 48 | // Optional. Default is "fiber_storage" 49 | Table string 50 | 51 | // Reset clears any existing keys in existing Table 52 | // 53 | // Optional. Default is false 54 | Reset bool 55 | 56 | // Time before deleting expired keys 57 | // 58 | // Optional. Default is 10 * time.Second 59 | GCInterval time.Duration 60 | 61 | //////////////////////////////////// 62 | // Adaptor related config options // 63 | //////////////////////////////////// 64 | 65 | maxIdleConns int 66 | maxOpenConns int 67 | connMaxLifetime time.Duration 68 | } 69 | 70 | // ConfigDefault is the default config 71 | var ConfigDefault = Config{ 72 | Db: nil, 73 | ConnectionURI: "", 74 | Host: "127.0.0.1", 75 | Port: 3306, 76 | Database: "fiber", 77 | Table: "fiber_storage", 78 | Reset: false, 79 | GCInterval: 10 * time.Second, 80 | maxOpenConns: 100, 81 | maxIdleConns: 100, 82 | connMaxLifetime: 1 * time.Second, 83 | } 84 | 85 | func (c Config) dsn() string { 86 | if c.ConnectionURI != "" { 87 | return c.ConnectionURI 88 | } 89 | return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", c.Username, c.Password, c.Host, c.Port, c.Database) 90 | } 91 | 92 | // Helper function to set default values 93 | func configDefault(config ...Config) Config { 94 | // Return default config if nothing provided 95 | if len(config) < 1 { 96 | return ConfigDefault 97 | } 98 | 99 | // Override default config 100 | cfg := config[0] 101 | 102 | // Set default values 103 | if cfg.Host == "" { 104 | cfg.Host = ConfigDefault.Host 105 | } 106 | if cfg.Port <= 0 { 107 | cfg.Port = ConfigDefault.Port 108 | } 109 | if cfg.Database == "" { 110 | cfg.Database = ConfigDefault.Database 111 | } 112 | if cfg.Table == "" { 113 | cfg.Table = ConfigDefault.Table 114 | } 115 | if int(cfg.GCInterval.Seconds()) <= 0 { 116 | cfg.GCInterval = ConfigDefault.GCInterval 117 | } 118 | return cfg 119 | } 120 | -------------------------------------------------------------------------------- /mysql/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/mysql/v2 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/go-sql-driver/mysql v1.9.2 7 | github.com/stretchr/testify v1.10.0 8 | github.com/testcontainers/testcontainers-go v0.37.0 9 | github.com/testcontainers/testcontainers-go/modules/mysql v0.37.0 10 | ) 11 | 12 | require ( 13 | dario.cat/mergo v1.0.1 // indirect 14 | filippo.io/edwards25519 v1.1.0 // indirect 15 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 16 | github.com/Microsoft/go-winio v0.6.2 // indirect 17 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/distribution/reference v0.6.0 // indirect 23 | github.com/docker/docker v28.0.1+incompatible // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/ebitengine/purego v0.8.2 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-logr/logr v1.4.2 // indirect 29 | github.com/go-logr/stdr v1.2.2 // indirect 30 | github.com/go-ole/go-ole v1.2.6 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 34 | github.com/klauspost/compress v1.17.4 // indirect 35 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 36 | github.com/magiconair/properties v1.8.10 // indirect 37 | github.com/moby/docker-image-spec v1.3.1 // indirect 38 | github.com/moby/patternmatcher v0.6.0 // indirect 39 | github.com/moby/sys/sequential v0.5.0 // indirect 40 | github.com/moby/sys/user v0.1.0 // indirect 41 | github.com/moby/sys/userns v0.1.0 // indirect 42 | github.com/moby/term v0.5.0 // indirect 43 | github.com/morikuni/aec v1.0.0 // indirect 44 | github.com/opencontainers/go-digest v1.0.0 // indirect 45 | github.com/opencontainers/image-spec v1.1.1 // indirect 46 | github.com/pkg/errors v0.9.1 // indirect 47 | github.com/pmezard/go-difflib v1.0.0 // indirect 48 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 49 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 50 | github.com/sirupsen/logrus v1.9.3 // indirect 51 | github.com/tklauser/go-sysconf v0.3.12 // indirect 52 | github.com/tklauser/numcpus v0.6.1 // indirect 53 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 54 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 55 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 56 | go.opentelemetry.io/otel v1.35.0 // indirect 57 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 58 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 59 | golang.org/x/crypto v0.37.0 // indirect 60 | golang.org/x/sys v0.32.0 // indirect 61 | gopkg.in/yaml.v3 v3.0.1 // indirect 62 | ) 63 | -------------------------------------------------------------------------------- /nats/config.go: -------------------------------------------------------------------------------- 1 | package nats 2 | 3 | import ( 4 | "context" 5 | "time" 6 | 7 | "github.com/nats-io/nats.go" 8 | "github.com/nats-io/nats.go/jetstream" 9 | ) 10 | 11 | // Config defines the config for storage. 12 | type Config struct { 13 | // Nats URLs, default "nats://127.0.0.1:4222". Can be comma separated list for multiple servers 14 | URLs string 15 | // Nats connection options. See nats_test.go for an example of how to use this. 16 | NatsOptions []nats.Option 17 | // Nats connection name 18 | ClientName string 19 | // Nats context 20 | Context context.Context 21 | // Nats key value config 22 | KeyValueConfig jetstream.KeyValueConfig 23 | // Wait for connection to be established, default: 250ms 24 | WaitForConnection time.Duration 25 | } 26 | 27 | // ConfigDefault is the default config 28 | var ConfigDefault = Config{ 29 | URLs: nats.DefaultURL, 30 | Context: context.Background(), 31 | ClientName: "fiber_storage", 32 | KeyValueConfig: jetstream.KeyValueConfig{ 33 | Bucket: "fiber_storage", 34 | }, 35 | WaitForConnection: 250 * time.Millisecond, 36 | } 37 | 38 | // Helper function to set default values 39 | func configDefault(config ...Config) Config { 40 | // Return default config if nothing provided 41 | if len(config) < 1 { 42 | return ConfigDefault 43 | } 44 | 45 | // Override default config 46 | cfg := config[0] 47 | 48 | // Set default values 49 | if cfg.URLs == "" { 50 | cfg.URLs = ConfigDefault.URLs 51 | } 52 | 53 | if cfg.Context == nil { 54 | cfg.Context = ConfigDefault.Context 55 | } 56 | 57 | if len(cfg.KeyValueConfig.Bucket) == 0 { 58 | cfg.KeyValueConfig.Bucket = ConfigDefault.KeyValueConfig.Bucket 59 | } 60 | 61 | if cfg.ClientName == "" { 62 | cfg.ClientName = ConfigDefault.ClientName 63 | } 64 | 65 | if cfg.WaitForConnection == 0 { 66 | cfg.WaitForConnection = ConfigDefault.WaitForConnection 67 | } 68 | 69 | return cfg 70 | } 71 | -------------------------------------------------------------------------------- /nats/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/nats 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/mdelapenya/tlscert v0.2.0 7 | github.com/nats-io/nats.go v1.43.0 8 | github.com/stretchr/testify v1.10.0 9 | github.com/testcontainers/testcontainers-go v0.37.0 10 | github.com/testcontainers/testcontainers-go/modules/nats v0.37.0 11 | ) 12 | 13 | require ( 14 | dario.cat/mergo v1.0.1 // indirect 15 | github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect 16 | github.com/Microsoft/go-winio v0.6.2 // indirect 17 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/distribution/reference v0.6.0 // indirect 23 | github.com/docker/docker v28.0.1+incompatible // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/ebitengine/purego v0.8.2 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-logr/logr v1.4.2 // indirect 29 | github.com/go-logr/stdr v1.2.2 // indirect 30 | github.com/go-ole/go-ole v1.2.6 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 34 | github.com/klauspost/compress v1.18.0 // indirect 35 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 36 | github.com/magiconair/properties v1.8.10 // indirect 37 | github.com/moby/docker-image-spec v1.3.1 // indirect 38 | github.com/moby/patternmatcher v0.6.0 // indirect 39 | github.com/moby/sys/sequential v0.5.0 // indirect 40 | github.com/moby/sys/user v0.1.0 // indirect 41 | github.com/moby/sys/userns v0.1.0 // indirect 42 | github.com/moby/term v0.5.0 // indirect 43 | github.com/morikuni/aec v1.0.0 // indirect 44 | github.com/nats-io/nkeys v0.4.11 // indirect 45 | github.com/nats-io/nuid v1.0.1 // indirect 46 | github.com/opencontainers/go-digest v1.0.0 // indirect 47 | github.com/opencontainers/image-spec v1.1.1 // indirect 48 | github.com/pkg/errors v0.9.1 // indirect 49 | github.com/pmezard/go-difflib v1.0.0 // indirect 50 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 51 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 52 | github.com/sirupsen/logrus v1.9.3 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sys v0.32.0 // indirect 63 | gopkg.in/yaml.v3 v3.0.1 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /nats/testdata/nats-tls.conf: -------------------------------------------------------------------------------- 1 | # Simple TLS config file 2 | 3 | port: 4443 4 | net: 0.0.0.0 # net interface 5 | 6 | tls { 7 | cert_file: "/tls/nats.crt" 8 | key_file: "/tls/nats.key" 9 | ca_file: "/tls/ca.crt" 10 | timeout: 2 11 | } 12 | -------------------------------------------------------------------------------- /neo4j/config.go: -------------------------------------------------------------------------------- 1 | package neo4j 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/neo4j/neo4j-go-driver/v5/neo4j" 7 | "github.com/neo4j/neo4j-go-driver/v5/neo4j/auth" 8 | "github.com/neo4j/neo4j-go-driver/v5/neo4j/config" 9 | ) 10 | 11 | type Config struct { 12 | // Connection pool. 13 | // 14 | // DB neo4j.DriverWithContext object will override connection uri and other connection fields. 15 | // 16 | // Optional. Default is nil. 17 | DB neo4j.DriverWithContext 18 | 19 | // Target Server 20 | // 21 | // Optional. Default is "neo4j://localhost" 22 | URI string 23 | 24 | // Connection authentication. 25 | // 26 | // Auth auth.TokenManager will override Username and Password fields. 27 | // 28 | // Optional. Default is nil. 29 | Auth auth.TokenManager 30 | 31 | // Connection configurations 32 | // 33 | // Optional. Default is nil 34 | Configurations []func(*config.Config) 35 | 36 | // Server username 37 | // 38 | // Optional. Default is "" 39 | Username string 40 | 41 | // Server password 42 | // 43 | // Optional. Default is "" 44 | Password string 45 | 46 | // Node name 47 | // 48 | // Optional. Default is "fiber_storage" 49 | Node string 50 | 51 | // Reset clears any existing keys (Nodes) 52 | // 53 | // Optional. Default is false 54 | Reset bool 55 | 56 | // Time before deleting expired keys (Nodes) 57 | // 58 | // Optional. Default is 10 * time.Second 59 | GCInterval time.Duration 60 | } 61 | 62 | var ConfigDefault = Config{ 63 | URI: "neo4j://localhost", 64 | Node: "fiber_storage", 65 | Reset: false, 66 | GCInterval: 10 * time.Second, 67 | } 68 | 69 | // Helper function to set default values 70 | func configDefault(config ...Config) Config { 71 | 72 | // Return default config if nothing provided 73 | if len(config) < 1 { 74 | return ConfigDefault 75 | } 76 | 77 | // Override default config 78 | cfg := config[0] 79 | 80 | // Set default values 81 | if cfg.URI == "" { 82 | cfg.URI = ConfigDefault.URI 83 | } 84 | 85 | if cfg.Auth == nil { 86 | if cfg.Username != "" && cfg.Password != "" { 87 | cfg.Auth = neo4j.BasicAuth(cfg.Username, cfg.Password, "") 88 | } else { 89 | cfg.Auth = neo4j.NoAuth() 90 | } 91 | } 92 | 93 | if cfg.Node == "" { 94 | cfg.Node = ConfigDefault.Node 95 | } 96 | 97 | if int(cfg.GCInterval.Seconds()) <= 0 { 98 | cfg.GCInterval = ConfigDefault.GCInterval 99 | } 100 | 101 | return cfg 102 | } 103 | -------------------------------------------------------------------------------- /neo4j/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/neo4j 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/neo4j/neo4j-go-driver/v5 v5.28.1 7 | github.com/stretchr/testify v1.10.0 8 | github.com/testcontainers/testcontainers-go v0.37.0 9 | github.com/testcontainers/testcontainers-go/modules/neo4j v0.37.0 10 | ) 11 | 12 | require ( 13 | dario.cat/mergo v1.0.1 // indirect 14 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 15 | github.com/Microsoft/go-winio v0.6.2 // indirect 16 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 17 | github.com/containerd/log v0.1.0 // indirect 18 | github.com/containerd/platforms v0.2.1 // indirect 19 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 20 | github.com/davecgh/go-spew v1.1.1 // indirect 21 | github.com/distribution/reference v0.6.0 // indirect 22 | github.com/docker/docker v28.0.1+incompatible // indirect 23 | github.com/docker/go-connections v0.5.0 // indirect 24 | github.com/docker/go-units v0.5.0 // indirect 25 | github.com/ebitengine/purego v0.8.2 // indirect 26 | github.com/felixge/httpsnoop v1.0.4 // indirect 27 | github.com/go-logr/logr v1.4.2 // indirect 28 | github.com/go-logr/stdr v1.2.2 // indirect 29 | github.com/go-ole/go-ole v1.2.6 // indirect 30 | github.com/gogo/protobuf v1.3.2 // indirect 31 | github.com/google/uuid v1.6.0 // indirect 32 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 33 | github.com/klauspost/compress v1.17.4 // indirect 34 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 35 | github.com/magiconair/properties v1.8.10 // indirect 36 | github.com/moby/docker-image-spec v1.3.1 // indirect 37 | github.com/moby/patternmatcher v0.6.0 // indirect 38 | github.com/moby/sys/sequential v0.5.0 // indirect 39 | github.com/moby/sys/user v0.1.0 // indirect 40 | github.com/moby/sys/userns v0.1.0 // indirect 41 | github.com/moby/term v0.5.0 // indirect 42 | github.com/morikuni/aec v1.0.0 // indirect 43 | github.com/opencontainers/go-digest v1.0.0 // indirect 44 | github.com/opencontainers/image-spec v1.1.1 // indirect 45 | github.com/pkg/errors v0.9.1 // indirect 46 | github.com/pmezard/go-difflib v1.0.0 // indirect 47 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 48 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 49 | github.com/sirupsen/logrus v1.9.3 // indirect 50 | github.com/tklauser/go-sysconf v0.3.12 // indirect 51 | github.com/tklauser/numcpus v0.6.1 // indirect 52 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 53 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 54 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 55 | go.opentelemetry.io/otel v1.35.0 // indirect 56 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 57 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 58 | golang.org/x/crypto v0.37.0 // indirect 59 | golang.org/x/sys v0.32.0 // indirect 60 | gopkg.in/yaml.v3 v3.0.1 // indirect 61 | ) 62 | -------------------------------------------------------------------------------- /pebble/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: pebble 3 | title: Pebble 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=pebble*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-pebble.yml?label=Tests) 9 | 10 | A fast key-value DB using [cockroachdb/pebble](https://github.com/cockroachdb/pebble) 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | 16 | - [Signatures](#signatures) 17 | - [Installation](#installation) 18 | - [Examples](#examples) 19 | - [Config](#config) 20 | - [Default Config](#default-config) 21 | 22 | ### Signatures 23 | 24 | ```go 25 | func New(config ...Config) Storage 26 | func (s *Storage) Get(key string) ([]byte, error) 27 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 28 | func (s *Storage) Delete(key string) error 29 | func (s *Storage) Reset() error 30 | func (s *Storage) Close() error 31 | func (s *Storage) Conn() *badger.DB 32 | ``` 33 | 34 | ### Installation 35 | 36 | Pebble is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 37 | ```bash 38 | go mod init github.com// 39 | ``` 40 | Note: This step is only required if you don't have an existing module. 41 | 42 | And then install the Pebble implementation: 43 | 44 | ```bash 45 | go get github.com/gofiber/storage/pebble/v2 46 | ``` 47 | 48 | ### Examples 49 | 50 | Import the storage package. 51 | 52 | ```go 53 | import "github.com/gofiber/storage/pebble/v2" 54 | ``` 55 | 56 | You can use the following possibilities to create a storage: 57 | 58 | ```go 59 | // Initialize default config 60 | store := pebble.New() 61 | 62 | // Initialize custom config 63 | store := pebble.New(pebble.Config{ 64 | Path: "db", 65 | WriteOptions: &pebble.WriteOptions{}, 66 | }) 67 | ``` 68 | 69 | ### Config 70 | 71 | ```go 72 | type Config struct { 73 | // Database name 74 | // 75 | // Optional. Default is "./db" 76 | Path string 77 | 78 | // Pass write options during write operations 79 | // 80 | // Optional. Default is nil 81 | WriteOptions &pebble.WriteOptions{} 82 | } 83 | ``` 84 | 85 | ### Default Config 86 | 87 | ```go 88 | var ConfigDefault = Config{ 89 | Path: "db", 90 | WriteOptions: &pebble.WriteOptions{}, 91 | } 92 | ``` 93 | -------------------------------------------------------------------------------- /pebble/config.go: -------------------------------------------------------------------------------- 1 | package pebble 2 | 3 | import "github.com/cockroachdb/pebble" 4 | 5 | type Config struct { 6 | Path string 7 | WriteOptions *pebble.WriteOptions 8 | } 9 | 10 | var ConfigDefault = Config{ 11 | Path: "db", 12 | WriteOptions: &pebble.WriteOptions{}, 13 | } 14 | 15 | func configDefault(config ...Config) Config { 16 | if len(config) < 1 { 17 | return configDefault(config...) 18 | } 19 | cfg := config[0] 20 | if cfg.Path == "" { 21 | cfg.Path = ConfigDefault.Path 22 | } 23 | return cfg 24 | } 25 | -------------------------------------------------------------------------------- /pebble/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/pebble/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/cockroachdb/pebble v1.0.0 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/DataDog/zstd v1.5.5 // indirect 12 | github.com/beorn7/perks v1.0.1 // indirect 13 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 14 | github.com/cockroachdb/errors v1.10.0 // indirect 15 | github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect 16 | github.com/cockroachdb/redact v1.1.5 // indirect 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/getsentry/sentry-go v0.23.0 // indirect 19 | github.com/gogo/protobuf v1.3.2 // indirect 20 | github.com/golang/protobuf v1.5.3 // indirect 21 | github.com/golang/snappy v0.0.4 // indirect 22 | github.com/klauspost/compress v1.16.7 // indirect 23 | github.com/kr/pretty v0.3.1 // indirect 24 | github.com/kr/text v0.2.0 // indirect 25 | github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect 26 | github.com/pkg/errors v0.9.1 // indirect 27 | github.com/pmezard/go-difflib v1.0.0 // indirect 28 | github.com/prometheus/client_golang v1.16.0 // indirect 29 | github.com/prometheus/client_model v0.4.0 // indirect 30 | github.com/prometheus/common v0.44.0 // indirect 31 | github.com/prometheus/procfs v0.11.1 // indirect 32 | github.com/rogpeppe/go-internal v1.11.0 // indirect 33 | golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect 34 | golang.org/x/sys v0.11.0 // indirect 35 | golang.org/x/text v0.12.0 // indirect 36 | google.golang.org/protobuf v1.33.0 // indirect 37 | gopkg.in/yaml.v3 v3.0.1 // indirect 38 | ) 39 | -------------------------------------------------------------------------------- /pebble/pebble_test.go: -------------------------------------------------------------------------------- 1 | package pebble 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | var testStore = New(Config{ 11 | Path: "test.db", 12 | WriteOptions: nil, 13 | }) 14 | 15 | func Test_Pebble_Set(t *testing.T) { 16 | var ( 17 | key = "john" 18 | val = []byte("doe") 19 | ) 20 | 21 | err := testStore.Set(key, val, 0) 22 | require.NoError(t, err) 23 | } 24 | 25 | func Test_Pebble_Set_Override(t *testing.T) { 26 | var ( 27 | key = "john" 28 | val = []byte("doe") 29 | ) 30 | 31 | err := testStore.Set(key, val, 0) 32 | require.NoError(t, err) 33 | 34 | err = testStore.Set(key, val, 0) 35 | require.NoError(t, err) 36 | } 37 | 38 | func Test_Pebble_Get(t *testing.T) { 39 | var ( 40 | key = "john" 41 | val = []byte("doe") 42 | ) 43 | 44 | err := testStore.Set(key, val, 0) 45 | require.NoError(t, err) 46 | 47 | result, err := testStore.Get(key) 48 | require.NoError(t, err) 49 | require.Equal(t, val, result) 50 | } 51 | 52 | func Test_Pebble_Set_Expiration(t *testing.T) { 53 | var ( 54 | key = "john" 55 | val = []byte("doe") 56 | exp = 1 * time.Second 57 | ) 58 | 59 | err := testStore.Set(key, val, exp) 60 | require.NoError(t, err) 61 | 62 | time.Sleep(1100 * time.Millisecond) 63 | } 64 | 65 | func Test_Pebble_Delete(t *testing.T) { 66 | var ( 67 | key = "john" 68 | val = []byte("doe") 69 | ) 70 | 71 | err := testStore.Set(key, val, 20) 72 | require.NoError(t, err) 73 | 74 | err = testStore.Delete(key) 75 | require.NoError(t, err) 76 | 77 | result, err := testStore.Get(key) 78 | require.Equal(t, "pebble: not found", err.Error()) 79 | require.Zero(t, len(result)) 80 | } 81 | 82 | func Test_Pebble_Reset(t *testing.T) { 83 | val := []byte("doe") 84 | 85 | err := testStore.Set("john1", val, 0) 86 | require.NoError(t, err) 87 | 88 | err = testStore.Set("john2", val, 0) 89 | require.NoError(t, err) 90 | 91 | err = testStore.Reset() 92 | require.NoError(t, err) 93 | 94 | _, err = testStore.Get("john1") 95 | require.NoError(t, err) 96 | 97 | _, err = testStore.Get("john2") 98 | require.NoError(t, err) 99 | } 100 | 101 | func Test_Pebble_Close(t *testing.T) { 102 | require.Nil(t, testStore.Close()) 103 | } 104 | 105 | func Test_Pebble_Conn(t *testing.T) { 106 | require.True(t, testStore.Conn() != nil) 107 | } 108 | 109 | func Benchmark_Pebble_Set(b *testing.B) { 110 | b.ReportAllocs() 111 | b.ResetTimer() 112 | 113 | var err error 114 | for i := 0; i < b.N; i++ { 115 | err = testStore.Set("john", []byte("doe"), 0) 116 | } 117 | 118 | require.NoError(b, err) 119 | } 120 | 121 | func Benchmark_Pebble_Get(b *testing.B) { 122 | err := testStore.Set("john", []byte("doe"), 0) 123 | require.NoError(b, err) 124 | 125 | b.ReportAllocs() 126 | b.ResetTimer() 127 | 128 | for i := 0; i < b.N; i++ { 129 | _, err = testStore.Get("john") 130 | } 131 | 132 | require.NoError(b, err) 133 | } 134 | 135 | func Benchmark_Pebble_SetAndDelete(b *testing.B) { 136 | b.ReportAllocs() 137 | b.ResetTimer() 138 | 139 | var err error 140 | for i := 0; i < b.N; i++ { 141 | _ = testStore.Set("john", []byte("doe"), 0) 142 | err = testStore.Delete("john") 143 | } 144 | 145 | require.NoError(b, err) 146 | } 147 | -------------------------------------------------------------------------------- /postgres/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/postgres/v3 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/jackc/pgx/v5 v5.7.5 7 | github.com/stretchr/testify v1.10.0 8 | github.com/testcontainers/testcontainers-go v0.37.0 9 | github.com/testcontainers/testcontainers-go/modules/postgres v0.37.0 10 | ) 11 | 12 | require ( 13 | dario.cat/mergo v1.0.1 // indirect 14 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 15 | github.com/Microsoft/go-winio v0.6.2 // indirect 16 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 17 | github.com/containerd/log v0.1.0 // indirect 18 | github.com/containerd/platforms v0.2.1 // indirect 19 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 20 | github.com/davecgh/go-spew v1.1.1 // indirect 21 | github.com/distribution/reference v0.6.0 // indirect 22 | github.com/docker/docker v28.0.1+incompatible // indirect 23 | github.com/docker/go-connections v0.5.0 // indirect 24 | github.com/docker/go-units v0.5.0 // indirect 25 | github.com/ebitengine/purego v0.8.2 // indirect 26 | github.com/felixge/httpsnoop v1.0.4 // indirect 27 | github.com/go-logr/logr v1.4.2 // indirect 28 | github.com/go-logr/stdr v1.2.2 // indirect 29 | github.com/go-ole/go-ole v1.2.6 // indirect 30 | github.com/gogo/protobuf v1.3.2 // indirect 31 | github.com/google/uuid v1.6.0 // indirect 32 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 33 | github.com/jackc/pgpassfile v1.0.0 // indirect 34 | github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect 35 | github.com/jackc/puddle/v2 v2.2.2 // indirect 36 | github.com/klauspost/compress v1.17.4 // indirect 37 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 38 | github.com/magiconair/properties v1.8.10 // indirect 39 | github.com/moby/docker-image-spec v1.3.1 // indirect 40 | github.com/moby/patternmatcher v0.6.0 // indirect 41 | github.com/moby/sys/sequential v0.5.0 // indirect 42 | github.com/moby/sys/user v0.1.0 // indirect 43 | github.com/moby/sys/userns v0.1.0 // indirect 44 | github.com/moby/term v0.5.0 // indirect 45 | github.com/morikuni/aec v1.0.0 // indirect 46 | github.com/opencontainers/go-digest v1.0.0 // indirect 47 | github.com/opencontainers/image-spec v1.1.1 // indirect 48 | github.com/pkg/errors v0.9.1 // indirect 49 | github.com/pmezard/go-difflib v1.0.0 // indirect 50 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 51 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 52 | github.com/sirupsen/logrus v1.9.3 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sync v0.13.0 // indirect 63 | golang.org/x/sys v0.32.0 // indirect 64 | golang.org/x/text v0.24.0 // indirect 65 | gopkg.in/yaml.v3 v3.0.1 // indirect 66 | ) 67 | -------------------------------------------------------------------------------- /redis/config.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "crypto/tls" 5 | "runtime" 6 | ) 7 | 8 | // Config defines the config for storage. 9 | type Config struct { 10 | // Host name where the DB is hosted 11 | // 12 | // Optional. Default is "127.0.0.1" 13 | Host string 14 | 15 | // Port where the DB is listening on 16 | // 17 | // Optional. Default is 6379 18 | Port int 19 | 20 | // Server username 21 | // 22 | // Optional. Default is "" 23 | Username string 24 | 25 | // Server password 26 | // 27 | // Optional. Default is "" 28 | Password string 29 | 30 | // Database to be selected after connecting to the server. 31 | // 32 | // Optional. Default is 0 33 | Database int 34 | 35 | // URL standard format Redis URL. If this is set all other config options, Host, Port, Username, Password, Database have no effect. 36 | // 37 | // Example: redis://:@localhost:6379/ 38 | // Optional. Default is "" 39 | URL string 40 | 41 | // Either a single address or a seed list of host:port addresses, this enables FailoverClient and ClusterClient 42 | // 43 | // Optional. Default is []string{} 44 | Addrs []string 45 | 46 | // MasterName is the sentinel master's name 47 | // 48 | // Optional. Default is "" 49 | MasterName string 50 | 51 | // ClientName will execute the `CLIENT SETNAME ClientName` command for each conn. 52 | // 53 | // Optional. Default is "" 54 | ClientName string 55 | 56 | // SentinelUsername 57 | // 58 | // Optional. Default is "" 59 | SentinelUsername string 60 | 61 | // SentinelPassword 62 | // 63 | // Optional. Default is "" 64 | SentinelPassword string 65 | 66 | // Reset clears any existing keys in existing Collection 67 | // 68 | // Optional. Default is false 69 | Reset bool 70 | 71 | // TLS Config to use. When set TLS will be negotiated. 72 | // 73 | // Optional. Default is nil 74 | TLSConfig *tls.Config 75 | 76 | // Maximum number of socket connections. 77 | // 78 | // Optional. Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS. 79 | PoolSize int 80 | } 81 | 82 | // ConfigDefault is the default config 83 | var ConfigDefault = Config{ 84 | Host: "127.0.0.1", 85 | Port: 6379, 86 | Username: "", 87 | Password: "", 88 | URL: "", 89 | Database: 0, 90 | Reset: false, 91 | TLSConfig: nil, 92 | PoolSize: 10 * runtime.GOMAXPROCS(0), 93 | Addrs: []string{}, 94 | MasterName: "", 95 | ClientName: "", 96 | SentinelUsername: "", 97 | SentinelPassword: "", 98 | } 99 | 100 | // Helper function to set default values 101 | func configDefault(config ...Config) Config { 102 | // Return default config if nothing provided 103 | if len(config) < 1 { 104 | return ConfigDefault 105 | } 106 | 107 | // Override default config 108 | cfg := config[0] 109 | 110 | // Set default values 111 | if cfg.Host == "" { 112 | cfg.Host = ConfigDefault.Host 113 | } 114 | if cfg.Port <= 0 { 115 | cfg.Port = ConfigDefault.Port 116 | } 117 | return cfg 118 | } 119 | -------------------------------------------------------------------------------- /ristretto/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ristretto 3 | title: Ristretto 4 | --- 5 | 6 | ![Release](https://img.shields.io/github/v/tag/gofiber/storage?filter=ristretto*) 7 | [![Discord](https://img.shields.io/discord/704680098577514527?style=flat&label=%F0%9F%92%AC%20discord&color=00ACD7)](https://gofiber.io/discord) 8 | ![Test](https://img.shields.io/github/actions/workflow/status/gofiber/storage/test-ristretto.yml?label=Tests) 9 | 10 | A Memory-bound storage driver using [`dgraph-io/ristretto`](https://github.com/dgraph-io/ristretto). 11 | 12 | **Note: Requires Go 1.19 and above** 13 | 14 | ### Table of Contents 15 | - [Signatures](#signatures) 16 | - [Installation](#installation) 17 | - [Examples](#examples) 18 | - [Config](#config) 19 | - [Default Config](#default-config) 20 | 21 | 22 | ### Signatures 23 | ```go 24 | func New(config ...Config) Storage 25 | func (s *Storage) Get(key string) ([]byte, error) 26 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error 27 | func (s *Storage) Delete(key string) error 28 | func (s *Storage) Reset() error 29 | func (s *Storage) Close() error 30 | func (s *Storage) Conn() *ristretto.Cache 31 | ``` 32 | 33 | ### Installation 34 | Ristretto is tested on the 2 last [Go versions](https://golang.org/dl/) with support for modules. So make sure to initialize one first if you didn't do that yet: 35 | ```bash 36 | go mod init github.com// 37 | ``` 38 | And then install the ristretto implementation: 39 | ```bash 40 | go get github.com/gofiber/storage/ristretto/v2 41 | ``` 42 | 43 | ### Examples 44 | Import the storage package. 45 | ```go 46 | import "github.com/gofiber/storage/ristretto/v2" 47 | ``` 48 | 49 | You can use the following possibilities to create a storage: 50 | ```go 51 | // Initialize default config 52 | store := ristretto.New() 53 | 54 | // Initialize custom config 55 | store := ristretto.New(ristretto.Config{ 56 | NumCounters: 1e7, // number of keys to track frequency of (10M). 57 | MaxCost: 1 << 30, // maximum cost of cache (1GB). 58 | BufferItems: 64, // number of keys per Get buffer. 59 | }) 60 | ``` 61 | 62 | ### Config 63 | ```go 64 | type Config struct { 65 | // NumCounters number of keys to track frequency of (10M). 66 | NumCounters int64 67 | 68 | // MaxCost maximum cost of cache (1GB). 69 | MaxCost int64 70 | 71 | // BufferItems number of keys per Get buffer. 72 | BufferItems int64 73 | } 74 | ``` 75 | 76 | ### Default Config 77 | ```go 78 | var ConfigDefault = Config{ 79 | NumCounters: 1e7, 80 | MaxCost: 1 << 30, 81 | BufferItems: 64, 82 | DefaultCost: 1, 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /ristretto/config.go: -------------------------------------------------------------------------------- 1 | package ristretto 2 | 3 | // Config defines the config for storage. 4 | type Config struct { 5 | // NumCounters number of keys to track frequency of (10M). 6 | NumCounters int64 7 | 8 | // MaxCost maximum cost of cache (1GB). 9 | MaxCost int64 10 | 11 | // BufferItems number of keys per Get buffer. 12 | BufferItems int64 13 | DefaultCost int64 14 | } 15 | 16 | var ConfigDefault = Config{ 17 | NumCounters: 1e7, 18 | MaxCost: 1 << 30, 19 | BufferItems: 64, 20 | DefaultCost: 1, 21 | } 22 | 23 | func configDefault(config ...Config) Config { 24 | if len(config) < 1 { 25 | return ConfigDefault 26 | } 27 | cfg := config[0] 28 | 29 | if cfg.NumCounters < 1 { 30 | cfg.NumCounters = ConfigDefault.NumCounters 31 | } 32 | 33 | if cfg.MaxCost < 1 { 34 | cfg.MaxCost = ConfigDefault.MaxCost 35 | } 36 | 37 | if cfg.BufferItems < 1 { 38 | cfg.BufferItems = ConfigDefault.BufferItems 39 | } 40 | 41 | if cfg.DefaultCost == 0 { 42 | cfg.DefaultCost = ConfigDefault.DefaultCost 43 | } 44 | 45 | return cfg 46 | } 47 | -------------------------------------------------------------------------------- /ristretto/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/ristretto/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/dgraph-io/ristretto v0.2.0 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 12 | github.com/davecgh/go-spew v1.1.1 // indirect 13 | github.com/dustin/go-humanize v1.0.1 // indirect 14 | github.com/pkg/errors v0.9.1 // indirect 15 | github.com/pmezard/go-difflib v1.0.0 // indirect 16 | golang.org/x/sys v0.11.0 // indirect 17 | gopkg.in/yaml.v3 v3.0.1 // indirect 18 | ) 19 | -------------------------------------------------------------------------------- /ristretto/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 2 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/dgraph-io/ristretto v0.2.0 h1:XAfl+7cmoUDWW/2Lx8TGZQjjxIQ2Ley9DSf52dru4WE= 6 | github.com/dgraph-io/ristretto v0.2.0/go.mod h1:8uBHCU/PBV4Ag0CJrP47b9Ofby5dqWNh4FicAdoqFNU= 7 | github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= 8 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 9 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 10 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 11 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 12 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 13 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 14 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 15 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 16 | golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= 17 | golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 18 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 19 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 20 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 21 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 22 | -------------------------------------------------------------------------------- /ristretto/ristretto.go: -------------------------------------------------------------------------------- 1 | package ristretto 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/dgraph-io/ristretto" 7 | ) 8 | 9 | // Storage interface that is implemented by storage providers. 10 | type Storage struct { 11 | cache *ristretto.Cache 12 | defaultCost int64 13 | } 14 | 15 | // New creates a new storage. 16 | func New(config ...Config) *Storage { 17 | cfg := configDefault(config...) 18 | cache, err := ristretto.NewCache(&ristretto.Config{ 19 | NumCounters: cfg.NumCounters, 20 | MaxCost: cfg.MaxCost, 21 | BufferItems: cfg.BufferItems, 22 | }) 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | store := &Storage{ 28 | cache: cache, 29 | defaultCost: cfg.DefaultCost, 30 | } 31 | 32 | return store 33 | } 34 | 35 | // Get gets the value for the given key. 36 | // `nil, nil` is returned when the key does not exist 37 | func (s *Storage) Get(key string) ([]byte, error) { 38 | if len(key) <= 0 { 39 | return nil, nil 40 | } 41 | 42 | item, found := s.cache.Get(key) 43 | if !found { 44 | return nil, nil 45 | } 46 | 47 | buf, asserted := item.([]byte) 48 | if !asserted { 49 | return nil, nil 50 | } 51 | 52 | return buf, nil 53 | } 54 | 55 | // Set stores the given value for the given key along 56 | // with an expiration value, time.Time{} means no expiration. 57 | // Empty key or value will be ignored without an error. 58 | func (s *Storage) Set(key string, val []byte, exp time.Duration) error { 59 | if len(key) <= 0 || len(val) <= 0 { 60 | return nil 61 | } 62 | saved := s.cache.SetWithTTL(key, val, s.defaultCost, exp) 63 | if !saved { 64 | return nil 65 | } 66 | return nil 67 | } 68 | 69 | // Delete deletes the value for the given key. 70 | // It returns no error if the storage does not contain the key, 71 | func (s *Storage) Delete(key string) error { 72 | if len(key) <= 0 { 73 | return nil 74 | } 75 | s.cache.Del(key) 76 | return nil 77 | } 78 | 79 | // Reset resets the storage and delete all keys. 80 | func (s *Storage) Reset() error { 81 | s.cache.Clear() 82 | return nil 83 | } 84 | 85 | // Close closes the storage and will stop any running garbage 86 | // collectors and open connections. 87 | func (s *Storage) Close() error { 88 | s.cache.Close() 89 | return nil 90 | } 91 | 92 | // Return database client 93 | func (s *Storage) Conn() *ristretto.Cache { 94 | return s.cache 95 | } 96 | -------------------------------------------------------------------------------- /rueidis/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/rueidis 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/gofiber/storage/testhelpers/redis v0.0.0-00010101000000-000000000000 7 | github.com/redis/rueidis v1.0.60 8 | github.com/stretchr/testify v1.10.0 9 | ) 10 | 11 | replace github.com/gofiber/storage/testhelpers/redis => ../testhelpers/redis 12 | 13 | require ( 14 | dario.cat/mergo v1.0.1 // indirect 15 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 16 | github.com/Microsoft/go-winio v0.6.2 // indirect 17 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/distribution/reference v0.6.0 // indirect 23 | github.com/docker/docker v28.0.1+incompatible // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/ebitengine/purego v0.8.2 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-logr/logr v1.4.2 // indirect 29 | github.com/go-logr/stdr v1.2.2 // indirect 30 | github.com/go-ole/go-ole v1.2.6 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/klauspost/compress v1.17.4 // indirect 34 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 35 | github.com/magiconair/properties v1.8.10 // indirect 36 | github.com/mdelapenya/tlscert v0.2.0 // indirect 37 | github.com/moby/docker-image-spec v1.3.1 // indirect 38 | github.com/moby/patternmatcher v0.6.0 // indirect 39 | github.com/moby/sys/sequential v0.5.0 // indirect 40 | github.com/moby/sys/user v0.1.0 // indirect 41 | github.com/moby/sys/userns v0.1.0 // indirect 42 | github.com/moby/term v0.5.0 // indirect 43 | github.com/morikuni/aec v1.0.0 // indirect 44 | github.com/opencontainers/go-digest v1.0.0 // indirect 45 | github.com/opencontainers/image-spec v1.1.1 // indirect 46 | github.com/pkg/errors v0.9.1 // indirect 47 | github.com/pmezard/go-difflib v1.0.0 // indirect 48 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 49 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 50 | github.com/sirupsen/logrus v1.9.3 // indirect 51 | github.com/testcontainers/testcontainers-go v0.37.0 // indirect 52 | github.com/testcontainers/testcontainers-go/modules/redis v0.37.0 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sys v0.32.0 // indirect 63 | gopkg.in/yaml.v3 v3.0.1 // indirect 64 | ) 65 | -------------------------------------------------------------------------------- /s3/config.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import "time" 4 | 5 | // Config defines the config for storage. 6 | type Config struct { 7 | // S3 bucket name 8 | Bucket string 9 | 10 | // AWS endpoint 11 | Endpoint string 12 | 13 | // AWS region 14 | Region string 15 | 16 | // Request timeout 17 | // 18 | // Optional. Default is 0 (no timeout) 19 | RequestTimeout time.Duration 20 | 21 | // Reset clears any existing keys in existing Bucket 22 | // 23 | // Optional. Default is false 24 | Reset bool 25 | 26 | // Credentials overrides AWS access key and AWS secret access key. Not recommended. 27 | // 28 | // Optional. Default is Credentials{} 29 | Credentials Credentials 30 | 31 | // The maximum number of times requests that encounter retryable failures should be attempted. 32 | // 33 | // Optional. Default is 3 34 | MaxAttempts int 35 | } 36 | 37 | type Credentials struct { 38 | AccessKey string 39 | SecretAccessKey string 40 | } 41 | 42 | // ConfigDefault is the default config 43 | var ConfigDefault = Config{ 44 | Bucket: "", 45 | Region: "", 46 | Endpoint: "", 47 | Credentials: Credentials{}, 48 | MaxAttempts: 3, 49 | RequestTimeout: 0, 50 | Reset: false, 51 | } 52 | 53 | // Helper function to set default values 54 | func configDefault(config ...Config) Config { 55 | // Return default config if nothing provided 56 | if len(config) < 1 { 57 | return ConfigDefault 58 | } 59 | 60 | // Override default config 61 | cfg := config[0] 62 | 63 | // Set default values 64 | if cfg.Bucket == "" { 65 | cfg.Bucket = ConfigDefault.Bucket 66 | } 67 | 68 | return cfg 69 | } 70 | -------------------------------------------------------------------------------- /s3/init_test.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "context" 5 | "os" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/require" 10 | "github.com/testcontainers/testcontainers-go" 11 | "github.com/testcontainers/testcontainers-go/modules/minio" 12 | "github.com/testcontainers/testcontainers-go/wait" 13 | ) 14 | 15 | const ( 16 | bucket = "testbucket" 17 | ) 18 | 19 | const ( 20 | // minioImage is the default image used for running S3 in tests. 21 | minioImage = "docker.io/minio/minio:latest" 22 | minioImageEnvVar string = "TEST_MINIO_IMAGE" 23 | minioUser string = "minio-user" 24 | minioPass string = "minio-password" 25 | ) 26 | 27 | func newTestStore(t testing.TB) *Storage { 28 | img := minioImage 29 | if imgFromEnv := os.Getenv(minioImageEnvVar); imgFromEnv != "" { 30 | img = imgFromEnv 31 | } 32 | 33 | ctx := context.Background() 34 | 35 | c, err := minio.Run(ctx, 36 | img, 37 | minio.WithUsername(minioUser), 38 | minio.WithPassword(minioPass), 39 | testcontainers.WithWaitStrategy( 40 | wait.ForListeningPort("9000/tcp"), 41 | wait.ForHTTP("/minio/health/live").WithPort("9000"), 42 | ), 43 | ) 44 | if err != nil { 45 | panic(err) 46 | } 47 | 48 | conn, err := c.ConnectionString(ctx) 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | testStore := New( 54 | Config{ 55 | Bucket: bucket, 56 | Endpoint: "http://" + conn, 57 | Region: "us-east-1", 58 | Credentials: Credentials{ 59 | AccessKey: minioUser, 60 | SecretAccessKey: minioPass, 61 | }, 62 | RequestTimeout: 3 * time.Second, 63 | }, 64 | ) 65 | 66 | // Create test bucket. 67 | err = testStore.CreateBucket(bucket) 68 | require.NoError(t, err) 69 | // Do not delete test bucket, as the container is disposed after each test. 70 | 71 | return testStore 72 | } 73 | -------------------------------------------------------------------------------- /s3/s3_methods.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "fmt" 7 | 8 | "github.com/aws/aws-sdk-go-v2/aws" 9 | "github.com/aws/aws-sdk-go-v2/service/s3" 10 | "github.com/aws/aws-sdk-go-v2/service/s3/types" 11 | ) 12 | 13 | // Additional methods for S3, but not required by gofiber Storage interface. 14 | 15 | // CreateBucket creates a new bucket. 16 | func (s *Storage) CreateBucket(bucket string) error { 17 | ctx, cancel := s.requestContext() 18 | defer cancel() 19 | 20 | _, err := s.svc.CreateBucket(ctx, &s3.CreateBucketInput{ 21 | Bucket: aws.String(bucket), 22 | }) 23 | 24 | return err 25 | } 26 | 27 | // DeleteBucket deletes a bucket. 28 | func (s *Storage) DeleteBucket(bucket string) error { 29 | ctx, cancel := s.requestContext() 30 | defer cancel() 31 | 32 | _, err := s.svc.DeleteBucket(ctx, &s3.DeleteBucketInput{ 33 | Bucket: aws.String(bucket), 34 | }) 35 | 36 | return err 37 | } 38 | 39 | // DeleteMany entries by keys. 40 | func (s *Storage) DeleteMany(keys ...string) error { 41 | if len(keys) <= 0 { 42 | return nil 43 | } 44 | 45 | var objects []types.ObjectIdentifier 46 | for _, k := range keys { 47 | objects = append(objects, types.ObjectIdentifier{ 48 | Key: aws.String(k), 49 | }) 50 | } 51 | 52 | ctx, cancel := s.requestContext() 53 | defer cancel() 54 | 55 | _, err := s.svc.DeleteObjects(ctx, &s3.DeleteObjectsInput{ 56 | Bucket: &s.bucket, 57 | Delete: &types.Delete{ 58 | Objects: objects, 59 | }, 60 | }) 61 | 62 | return err 63 | } 64 | 65 | // SetWithChecksum sets key with value and checksum. 66 | // 67 | // Currently 4 algorithms are supported: 68 | // - types.ChecksumAlgorithmCrc32 (`CRC32`) 69 | // - types.ChecksumAlgorithmCrc32c (`CRC32C`) 70 | // - types.ChecksumAlgorithmSha1 (`SHA1`) 71 | // - types.ChecksumAlgorithmSha256 (`SHA256`) 72 | // 73 | // For more information, see [PutObjectInput](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3#PutObjectInput). 74 | func (s *Storage) SetWithChecksum(key string, val []byte, checksum map[types.ChecksumAlgorithm][]byte) error { 75 | if len(key) <= 0 { 76 | return nil 77 | } 78 | 79 | poi := s3.PutObjectInput{ 80 | Bucket: &s.bucket, 81 | Key: aws.String(key), 82 | Body: bytes.NewReader(val), 83 | } 84 | 85 | for alg, sum := range checksum { 86 | // S3 requires base64 encoded checksum. 87 | b64str := base64.StdEncoding.EncodeToString(sum) 88 | 89 | switch alg { 90 | case types.ChecksumAlgorithmCrc32: 91 | poi.ChecksumCRC32 = aws.String(b64str) 92 | case types.ChecksumAlgorithmCrc32c: 93 | poi.ChecksumCRC32C = aws.String(b64str) 94 | case types.ChecksumAlgorithmSha1: 95 | poi.ChecksumSHA1 = aws.String(b64str) 96 | case types.ChecksumAlgorithmSha256: 97 | poi.ChecksumSHA256 = aws.String(b64str) 98 | default: 99 | return fmt.Errorf("invalid checksum algorithm: %s", alg) 100 | } 101 | } 102 | 103 | ctx, cancel := s.requestContext() 104 | defer cancel() 105 | 106 | _, err := s.uploader.Upload(ctx, &poi) 107 | 108 | return err 109 | } 110 | -------------------------------------------------------------------------------- /s3/s3_methods_test.go: -------------------------------------------------------------------------------- 1 | package s3 2 | 3 | import ( 4 | "crypto/sha256" 5 | "testing" 6 | 7 | "github.com/aws/aws-sdk-go-v2/service/s3/types" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | func Test_S3_CreateDeleteBucket(t *testing.T) { 12 | bkt := "test-new-bucket" 13 | 14 | testStore := newTestStore(t) 15 | defer testStore.Close() 16 | 17 | err := testStore.CreateBucket(bkt) 18 | require.NoError(t, err) 19 | 20 | err = testStore.DeleteBucket(bkt) 21 | require.NoError(t, err) 22 | } 23 | 24 | func Test_S3_DeleteMany(t *testing.T) { 25 | val := []byte("doe") 26 | 27 | testStore := newTestStore(t) 28 | defer testStore.Close() 29 | 30 | err := testStore.Set("john1", val, 0) 31 | require.NoError(t, err) 32 | 33 | err = testStore.Set("john2", val, 0) 34 | require.NoError(t, err) 35 | 36 | err = testStore.Set("john3", val, 0) 37 | require.NoError(t, err) 38 | 39 | err = testStore.DeleteMany("john1", "john2") 40 | require.NoError(t, err) 41 | 42 | result, err := testStore.Get("john1") 43 | require.NoError(t, err) 44 | require.Zero(t, len(result)) 45 | 46 | result, err = testStore.Get("john2") 47 | require.NoError(t, err) 48 | require.Zero(t, len(result)) 49 | 50 | result, err = testStore.Get("john3") 51 | require.NoError(t, err) 52 | require.Equal(t, val, result) 53 | } 54 | 55 | func Test_S3_SetWithChecksum(t *testing.T) { 56 | var ( 57 | key = "set-with-checksum" 58 | val = []byte("doe") 59 | ) 60 | 61 | // Create SHA-256 hash and get checksum. 62 | sha256Hash := sha256.New() 63 | sha256Hash.Write(val) 64 | sha256sum := sha256Hash.Sum(nil) 65 | 66 | checksum := map[types.ChecksumAlgorithm][]byte{ 67 | types.ChecksumAlgorithmSha256: sha256sum, 68 | } 69 | 70 | testStore := newTestStore(t) 71 | defer testStore.Close() 72 | 73 | err := testStore.SetWithChecksum(key, val, checksum) 74 | require.NoError(t, err) 75 | 76 | result, err := testStore.Get(key) 77 | require.NoError(t, err) 78 | 79 | // Compare value. 80 | require.Equal(t, result, val) 81 | 82 | // Compare checksum. 83 | hash2 := sha256.New() 84 | hash2.Write(result) 85 | sha256sum2 := hash2.Sum(nil) 86 | require.Equal(t, sha256sum, sha256sum2) 87 | } 88 | -------------------------------------------------------------------------------- /scylladb/config.go: -------------------------------------------------------------------------------- 1 | package scylladb 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/gocql/gocql" 7 | ) 8 | 9 | type Config struct { 10 | // Session is provided by the user to use an existing ScyllaDb session 11 | // 12 | // Optional. Default is nil 13 | Session *gocql.Session 14 | 15 | // Keyspace name 16 | // 17 | // Optional. Default is "fiber" 18 | Keyspace string 19 | 20 | // Hosts are an array of network addresses for establishing initial connections. 21 | // You have the flexibility to specify one or multiple addresses as needed. 22 | // 23 | // Optional. Default is "127.0.0.1" 24 | Hosts []string 25 | 26 | // Port where the ScyllaDb cluster is listening on 27 | // 28 | // Optional. Default is 9042 29 | Port int 30 | 31 | // Username for ScyllaDb cluster 32 | // 33 | // Optional. Default is "" 34 | Username string 35 | 36 | // Password for ScyllaDb cluster 37 | // 38 | // Optional. Default is "" 39 | Password string 40 | 41 | // Table name 42 | // 43 | // Optional. Default is "fiber_storage" 44 | Table string 45 | 46 | // Level of the consistency 47 | // 48 | // Optional. Default is "LOCAL_ONE" 49 | Consistency string 50 | 51 | // SslOpts configures TLS use. 52 | // 53 | // Optional. Default is nil 54 | SslOpts *gocql.SslOptions 55 | 56 | // Reset clears any existing keys in existing Table 57 | // 58 | // Optional. Default is false 59 | Reset bool 60 | 61 | // DisableInitialHostLookup disables the initial host lookup 62 | // 63 | // Optional. Default is false 64 | DisableInitialHostLookup bool 65 | } 66 | 67 | // ConfigDefault is the default config 68 | var ConfigDefault = Config{ 69 | Session: nil, 70 | Keyspace: "fiber", 71 | Hosts: []string{"127.0.0.1"}, 72 | Username: "", 73 | Password: "", 74 | Port: 9042, 75 | Table: "fiber_storage", 76 | Consistency: "LOCAL_ONE", 77 | SslOpts: nil, 78 | Reset: false, 79 | DisableInitialHostLookup: false, 80 | } 81 | 82 | // configDefault helps to set a default config 83 | func configDefault(config ...Config) Config { 84 | // Return default config if nothing provided 85 | if len(config) < 1 { 86 | return ConfigDefault 87 | } 88 | 89 | // Override default config 90 | cfg := config[0] 91 | 92 | // Set default values 93 | if cfg.Hosts == nil { 94 | cfg.Hosts = ConfigDefault.Hosts 95 | } 96 | if cfg.Port <= 0 { 97 | cfg.Port = ConfigDefault.Port 98 | } 99 | if len(strings.TrimSpace(cfg.Table)) == 0 { 100 | cfg.Table = ConfigDefault.Table 101 | } 102 | if len(strings.TrimSpace(cfg.Keyspace)) == 0 { 103 | cfg.Keyspace = ConfigDefault.Keyspace 104 | } 105 | if len(strings.TrimSpace(cfg.Consistency)) == 0 { 106 | cfg.Consistency = ConfigDefault.Consistency 107 | } 108 | return cfg 109 | } 110 | -------------------------------------------------------------------------------- /sqlite3/config.go: -------------------------------------------------------------------------------- 1 | package sqlite3 2 | 3 | import "time" 4 | 5 | // Config defines the config for storage. 6 | type Config struct { 7 | // Database name 8 | // 9 | // Optional. Default is "fiber" 10 | Database string 11 | 12 | // Table name 13 | // 14 | // Optional. Default is "fiber_storage" 15 | Table string 16 | 17 | // Reset clears any existing keys in existing Table 18 | // 19 | // Optional. Default is false 20 | Reset bool 21 | 22 | // Time before deleting expired keys 23 | // 24 | // Optional. Default is 10 * time.Second 25 | GCInterval time.Duration 26 | 27 | // ////////////////////////////////// 28 | // Adaptor related config options // 29 | // ////////////////////////////////// 30 | 31 | // MaxIdleConns sets the maximum number of connections in the idle connection pool. 32 | // 33 | // Optional. Default is 100. 34 | MaxIdleConns int 35 | 36 | // MaxOpenConns sets the maximum number of open connections to the database. 37 | // 38 | // Optional. Default is 100. 39 | MaxOpenConns int 40 | 41 | // ConnMaxLifetime sets the maximum amount of time a connection may be reused. 42 | // 43 | // Optional. Default is 1 second. 44 | ConnMaxLifetime time.Duration 45 | } 46 | 47 | // ConfigDefault is the default config 48 | var ConfigDefault = Config{ 49 | // General config options 50 | Database: "./fiber.sqlite3", 51 | Table: "fiber_storage", 52 | Reset: false, 53 | GCInterval: 10 * time.Second, 54 | 55 | // Adaptor related config options 56 | MaxOpenConns: 100, 57 | MaxIdleConns: 100, 58 | ConnMaxLifetime: 1 * time.Second, 59 | } 60 | 61 | // Helper function to set default values 62 | func configDefault(config ...Config) Config { 63 | // Return default config if nothing provided 64 | if len(config) < 1 { 65 | return ConfigDefault 66 | } 67 | 68 | // Override default config 69 | cfg := config[0] 70 | 71 | // Set default values 72 | if cfg.Database == "" { 73 | cfg.Database = ConfigDefault.Database 74 | } 75 | if cfg.Table == "" { 76 | cfg.Table = ConfigDefault.Table 77 | } 78 | if int(cfg.GCInterval.Seconds()) <= 0 { 79 | cfg.GCInterval = ConfigDefault.GCInterval 80 | } 81 | if cfg.MaxIdleConns <= 0 { 82 | cfg.MaxIdleConns = ConfigDefault.MaxIdleConns 83 | } 84 | if cfg.MaxOpenConns <= 0 { 85 | cfg.MaxOpenConns = ConfigDefault.MaxOpenConns 86 | } 87 | if cfg.ConnMaxLifetime == 0 { 88 | cfg.ConnMaxLifetime = ConfigDefault.ConnMaxLifetime 89 | } 90 | return cfg 91 | } 92 | -------------------------------------------------------------------------------- /sqlite3/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/sqlite3/v2 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/mattn/go-sqlite3 v1.14.28 7 | github.com/stretchr/testify v1.10.0 8 | ) 9 | 10 | require ( 11 | github.com/davecgh/go-spew v1.1.1 // indirect 12 | github.com/pmezard/go-difflib v1.0.0 // indirect 13 | gopkg.in/yaml.v3 v3.0.1 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /sqlite3/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 2 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 | github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A= 4 | github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= 5 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= 8 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 10 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 11 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 12 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 13 | -------------------------------------------------------------------------------- /storage.go: -------------------------------------------------------------------------------- 1 | package storage 2 | 3 | import "time" 4 | 5 | // Storage interface for communicating with different database/key-value 6 | // providers. Visit https://github.com/gofiber/storage for more info. 7 | type Storage interface { 8 | // Get gets the value for the given key. 9 | // `nil, nil` is returned when the key does not exist 10 | Get(key string) ([]byte, error) 11 | 12 | // Set stores the given value for the given key along 13 | // with an expiration value, 0 means no expiration. 14 | // Empty key or value will be ignored without an error. 15 | Set(key string, val []byte, exp time.Duration) error 16 | 17 | // Delete deletes the value for the given key. 18 | // It returns no error if the storage does not contain the key, 19 | Delete(key string) error 20 | 21 | // Reset resets the storage and delete all keys. 22 | Reset() error 23 | 24 | // Close closes the storage and will stop any running garbage 25 | // collectors and open connections. 26 | Close() error 27 | } 28 | -------------------------------------------------------------------------------- /testhelpers/redis/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/testhelpers/redis 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/redis/go-redis/v9 v9.9.0 7 | github.com/stretchr/testify v1.10.0 8 | github.com/testcontainers/testcontainers-go v0.37.0 9 | github.com/testcontainers/testcontainers-go/modules/redis v0.37.0 10 | ) 11 | 12 | require ( 13 | dario.cat/mergo v1.0.1 // indirect 14 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 15 | github.com/Microsoft/go-winio v0.6.2 // indirect 16 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 17 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 23 | github.com/distribution/reference v0.6.0 // indirect 24 | github.com/docker/docker v28.0.1+incompatible // indirect 25 | github.com/docker/go-connections v0.5.0 // indirect 26 | github.com/docker/go-units v0.5.0 // indirect 27 | github.com/ebitengine/purego v0.8.2 // indirect 28 | github.com/felixge/httpsnoop v1.0.4 // indirect 29 | github.com/go-logr/logr v1.4.2 // indirect 30 | github.com/go-logr/stdr v1.2.2 // indirect 31 | github.com/go-ole/go-ole v1.2.6 // indirect 32 | github.com/gogo/protobuf v1.3.2 // indirect 33 | github.com/google/uuid v1.6.0 // indirect 34 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect 35 | github.com/klauspost/compress v1.17.4 // indirect 36 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 37 | github.com/magiconair/properties v1.8.10 // indirect 38 | github.com/mdelapenya/tlscert v0.2.0 // indirect 39 | github.com/moby/docker-image-spec v1.3.1 // indirect 40 | github.com/moby/patternmatcher v0.6.0 // indirect 41 | github.com/moby/sys/sequential v0.5.0 // indirect 42 | github.com/moby/sys/user v0.1.0 // indirect 43 | github.com/moby/sys/userns v0.1.0 // indirect 44 | github.com/moby/term v0.5.0 // indirect 45 | github.com/morikuni/aec v1.0.0 // indirect 46 | github.com/opencontainers/go-digest v1.0.0 // indirect 47 | github.com/opencontainers/image-spec v1.1.1 // indirect 48 | github.com/pkg/errors v0.9.1 // indirect 49 | github.com/pmezard/go-difflib v1.0.0 // indirect 50 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 51 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 52 | github.com/sirupsen/logrus v1.9.3 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/sdk v1.32.0 // indirect 61 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 62 | golang.org/x/crypto v0.37.0 // indirect 63 | golang.org/x/sys v0.32.0 // indirect 64 | google.golang.org/grpc v1.70.0 // indirect 65 | google.golang.org/protobuf v1.36.5 // indirect 66 | gopkg.in/yaml.v3 v3.0.1 // indirect 67 | ) 68 | -------------------------------------------------------------------------------- /valkey/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gofiber/storage/valkey 2 | 3 | go 1.23.0 4 | 5 | require ( 6 | github.com/gofiber/storage/testhelpers/redis v0.0.0-00010101000000-000000000000 7 | github.com/stretchr/testify v1.10.0 8 | github.com/valkey-io/valkey-go v1.0.60 9 | ) 10 | 11 | replace github.com/gofiber/storage/testhelpers/redis => ../testhelpers/redis 12 | 13 | require ( 14 | dario.cat/mergo v1.0.1 // indirect 15 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 16 | github.com/Microsoft/go-winio v0.6.2 // indirect 17 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 18 | github.com/containerd/log v0.1.0 // indirect 19 | github.com/containerd/platforms v0.2.1 // indirect 20 | github.com/cpuguy83/dockercfg v0.3.2 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/distribution/reference v0.6.0 // indirect 23 | github.com/docker/docker v28.0.1+incompatible // indirect 24 | github.com/docker/go-connections v0.5.0 // indirect 25 | github.com/docker/go-units v0.5.0 // indirect 26 | github.com/ebitengine/purego v0.8.2 // indirect 27 | github.com/felixge/httpsnoop v1.0.4 // indirect 28 | github.com/go-logr/logr v1.4.2 // indirect 29 | github.com/go-logr/stdr v1.2.2 // indirect 30 | github.com/go-ole/go-ole v1.2.6 // indirect 31 | github.com/gogo/protobuf v1.3.2 // indirect 32 | github.com/google/uuid v1.6.0 // indirect 33 | github.com/klauspost/compress v1.17.4 // indirect 34 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 35 | github.com/magiconair/properties v1.8.10 // indirect 36 | github.com/mdelapenya/tlscert v0.2.0 // indirect 37 | github.com/moby/docker-image-spec v1.3.1 // indirect 38 | github.com/moby/patternmatcher v0.6.0 // indirect 39 | github.com/moby/sys/sequential v0.5.0 // indirect 40 | github.com/moby/sys/user v0.1.0 // indirect 41 | github.com/moby/sys/userns v0.1.0 // indirect 42 | github.com/moby/term v0.5.0 // indirect 43 | github.com/morikuni/aec v1.0.0 // indirect 44 | github.com/opencontainers/go-digest v1.0.0 // indirect 45 | github.com/opencontainers/image-spec v1.1.1 // indirect 46 | github.com/pkg/errors v0.9.1 // indirect 47 | github.com/pmezard/go-difflib v1.0.0 // indirect 48 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect 49 | github.com/shirou/gopsutil/v4 v4.25.1 // indirect 50 | github.com/sirupsen/logrus v1.9.3 // indirect 51 | github.com/testcontainers/testcontainers-go v0.37.0 // indirect 52 | github.com/testcontainers/testcontainers-go/modules/redis v0.37.0 // indirect 53 | github.com/tklauser/go-sysconf v0.3.12 // indirect 54 | github.com/tklauser/numcpus v0.6.1 // indirect 55 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 56 | go.opentelemetry.io/auto/sdk v1.1.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect 58 | go.opentelemetry.io/otel v1.35.0 // indirect 59 | go.opentelemetry.io/otel/metric v1.35.0 // indirect 60 | go.opentelemetry.io/otel/trace v1.35.0 // indirect 61 | golang.org/x/crypto v0.37.0 // indirect 62 | golang.org/x/sys v0.32.0 // indirect 63 | gopkg.in/yaml.v3 v3.0.1 // indirect 64 | ) 65 | --------------------------------------------------------------------------------