├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── dependabot.yml └── workflows │ ├── build.yml │ └── release_pkg.yml ├── .gitignore ├── .go-version ├── .mergify.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── assets └── logo.png ├── bin └── release.sh ├── config.toml ├── go.mod ├── go.sum ├── pool.go ├── pool_test.go ├── renovate.json ├── techstack.md └── techstack.yml /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Docs: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 2 | * @clivern 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: clivern 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **Development or production environment** 11 | - OS: [e.g. Ubuntu 18.04] 12 | - Go 1.13 13 | 14 | **Additional context** 15 | Add any other context about the problem here. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Additional context** 14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | go: ['1.19'] 14 | name: Go ${{ matrix.go }} run 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Setup go 18 | uses: actions/setup-go@v3 19 | with: 20 | go-version: ${{ matrix.go }} 21 | 22 | - name: Get dependencies 23 | run: | 24 | export PATH=${PATH}:`go env GOPATH`/bin 25 | make install_revive 26 | 27 | - name: Run make ci 28 | run: | 29 | export PATH=${PATH}:`go env GOPATH`/bin 30 | go get -t . 31 | make ci 32 | git status 33 | git diff > diff.log 34 | cat diff.log 35 | git clean -fd 36 | git reset --hard 37 | make verify 38 | -------------------------------------------------------------------------------- /.github/workflows/release_pkg.yml: -------------------------------------------------------------------------------- 1 | name: ReleasePkg 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - 13 | name: Checkout 14 | uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | - 18 | name: Set up Go 19 | uses: actions/setup-go@v3 20 | with: 21 | go-version: 1.19 22 | 23 | - name: Update checksum database 24 | run: | 25 | ./bin/release.sh 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # dist dir 15 | dist 16 | 17 | sync 18 | 19 | *.db 20 | 21 | coverage.html 22 | -------------------------------------------------------------------------------- /.go-version: -------------------------------------------------------------------------------- 1 | 1.19 2 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | --- 2 | pull_request_rules: 3 | - 4 | actions: 5 | merge: 6 | method: squash 7 | conditions: 8 | - author!=Clivern 9 | - approved-reviews-by=Clivern 10 | - label=release 11 | name: "Automatic Merge 🚀" 12 | - 13 | actions: 14 | merge: 15 | method: merge 16 | conditions: 17 | - author=Clivern 18 | - label=release 19 | name: "Automatic Merge 🚀" 20 | - 21 | actions: 22 | merge: 23 | method: squash 24 | conditions: 25 | - "author=renovate[bot]" 26 | - label=release 27 | name: "Automatic Merge for Renovate PRs 🚀" 28 | - 29 | actions: 30 | comment: 31 | message: "Nice! PR merged successfully." 32 | conditions: 33 | - merged 34 | name: "Merge Done 🚀" 35 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hello@clivern.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | - With issues: 4 | - Use the search tool before opening a new issue. 5 | - Please provide source code and commit sha if you found a bug. 6 | - Review existing issues and provide feedback or react to them. 7 | 8 | - With pull requests: 9 | - Open your pull request against `main` 10 | - Your pull request should have no more than two commits, if not you should squash them. 11 | - It should pass all tests in the available continuous integrations systems such as TravisCI. 12 | - You should add/modify tests to cover your proposed code changes. 13 | - If your pull request contains a new feature, please document it on the README. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Clivern 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 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO ?= go 2 | GOFMT ?= $(GO)fmt 3 | pkgs = ./... 4 | 5 | 6 | help: Makefile 7 | @echo 8 | @echo " Choose a command run in Garment:" 9 | @echo 10 | @sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /' 11 | @echo 12 | 13 | 14 | ## install_revive: Install revive for linting. 15 | .PHONY: install_revive 16 | install_revive: 17 | @echo ">> ============= Install Revive ============= <<" 18 | $(GO) install github.com/mgechev/revive@latest 19 | 20 | 21 | ## style: Check code style. 22 | .PHONY: style 23 | style: 24 | @echo ">> ============= Checking Code Style ============= <<" 25 | @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ 26 | if [ -n "$${fmtRes}" ]; then \ 27 | echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ 28 | echo "Please ensure you are using $$($(GO) version) for formatting code."; \ 29 | exit 1; \ 30 | fi 31 | 32 | 33 | ## check_license: Check if license header on all files. 34 | .PHONY: check_license 35 | check_license: 36 | @echo ">> ============= Checking License Header ============= <<" 37 | @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ 38 | awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ 39 | done); \ 40 | if [ -n "$${licRes}" ]; then \ 41 | echo "license header checking failed:"; echo "$${licRes}"; \ 42 | exit 1; \ 43 | fi 44 | 45 | 46 | ## test_short: Run test cases with short flag. 47 | .PHONY: test_short 48 | test_short: 49 | @echo ">> ============= Running Short Tests ============= <<" 50 | $(GO) clean -testcache 51 | $(GO) test -mod=readonly -short $(pkgs) 52 | 53 | 54 | ## test: Run test cases. 55 | .PHONY: test 56 | test: 57 | @echo ">> ============= Running All Tests ============= <<" 58 | $(GO) clean -testcache 59 | $(GO) test -mod=readonly -run=Unit -bench=. -benchmem -v -cover $(pkgs) 60 | 61 | 62 | ## lint: Lint the code. 63 | .PHONY: lint 64 | lint: 65 | @echo ">> ============= Lint All Files ============= <<" 66 | revive -config config.toml -exclude vendor/... -formatter friendly ./... 67 | 68 | 69 | ## verify: Verify dependencies 70 | .PHONY: verify 71 | verify: 72 | @echo ">> ============= List Dependencies ============= <<" 73 | $(GO) list -m all 74 | @echo ">> ============= Verify Dependencies ============= <<" 75 | $(GO) mod verify 76 | 77 | 78 | ## format: Format the code. 79 | .PHONY: format 80 | format: 81 | @echo ">> ============= Formatting Code ============= <<" 82 | $(GO) fmt $(pkgs) 83 | 84 | 85 | ## vet: Examines source code and reports suspicious constructs. 86 | .PHONY: vet 87 | vet: 88 | @echo ">> ============= Vetting Code ============= <<" 89 | $(GO) vet $(pkgs) 90 | 91 | 92 | ## coverage: Create HTML coverage report 93 | .PHONY: coverage 94 | coverage: 95 | @echo ">> ============= Coverage ============= <<" 96 | rm -f coverage.html cover.out 97 | $(GO) test -mod=readonly -coverprofile=cover.out $(pkgs) 98 | go tool cover -html=cover.out -o coverage.html 99 | 100 | 101 | ## ci: Run all CI tests. 102 | .PHONY: ci 103 | ci: style check_license test vet lint 104 | @echo "\n==> All quality checks passed" 105 | 106 | 107 | .PHONY: help 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

Garment

4 |

A Thread Safe Connection Pooling.

5 |

6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |

22 |

23 | 24 | Garment retains a single connection pool for different database types used inside you application (MySQL, Redis, Etcd ... etc). Please note that garment won't be needed and not recommended if you already preserve the same connection pool across your application sub packages. 25 | 26 | 27 | ## Documentation 28 | 29 | #### Usage 30 | 31 | Install the package with: 32 | 33 | ```zsh 34 | $ go get github.com/norwik/garment 35 | ``` 36 | 37 | Here is an example: 38 | 39 | ```golang 40 | package main 41 | 42 | import ( 43 | "errors" 44 | "fmt" 45 | 46 | "github.com/norwik/garment" 47 | ) 48 | 49 | type Database struct { 50 | State string 51 | } 52 | 53 | func (d *Database) GetState() string { 54 | return d.State 55 | } 56 | 57 | func (d *Database) Terminate() { 58 | d.State = "disconnected" 59 | } 60 | 61 | func (d *Database) Close() { 62 | d.State = "disconnected" 63 | } 64 | 65 | func (d *Database) Reconnect() { 66 | d.State = "connected" 67 | } 68 | 69 | func (d *Database) Ping() bool { 70 | if d.State == "connected" { 71 | return true 72 | } 73 | 74 | return false 75 | } 76 | 77 | func main() { 78 | pool := garment.NewPool() 79 | 80 | ping := func(con interface{}) error { 81 | if con.(*Database).Ping() { 82 | return nil 83 | } 84 | 85 | return errors.New("DB connection is lost") 86 | } 87 | 88 | close := func(con interface{}) error { 89 | con.(*Database).Close() 90 | 91 | return nil 92 | } 93 | 94 | reconnect := func(con interface{}) error { 95 | con.(*Database).Reconnect() 96 | 97 | return nil 98 | } 99 | 100 | pool.Set("db", &Database{State: "connected"}, ping, close, reconnect) 101 | 102 | fmt.Println(pool.Count()) // 1 103 | 104 | fmt.Println(pool.Has("db")) // true 105 | fmt.Println(pool.Ping("db")) // 106 | 107 | fmt.Println(pool.Get("db").(*Database).GetState()) // connected 108 | 109 | pool.Close("db") 110 | 111 | fmt.Println(pool.Get("db").(*Database).GetState()) // disconnected 112 | 113 | pool.Reconnect("db") 114 | 115 | fmt.Println(pool.Get("db").(*Database).GetState()) // connected 116 | 117 | pool.Get("db").(*Database).Terminate() 118 | 119 | fmt.Println(pool.Get("db").(*Database).GetState()) // disconnected 120 | 121 | pool.Remove("db") 122 | 123 | fmt.Println(pool.Count()) // 0 124 | } 125 | ``` 126 | 127 | ## Versioning 128 | 129 | For transparency into our release cycle and in striving to maintain backward compatibility, Garment is maintained under the [Semantic Versioning guidelines](https://semver.org/) and release process is predictable and business-friendly. 130 | 131 | See the [Releases section of our GitHub project](https://github.com/norwik/garment/releases) for changelogs for each release version of Garment. It contains summaries of the most noteworthy changes made in each release. 132 | 133 | 134 | ## Bug tracker 135 | 136 | If you have any suggestions, bug reports, or annoyances please report them to our issue tracker at https://github.com/norwik/garment/issues 137 | 138 | 139 | ## Security Issues 140 | 141 | If you discover a security vulnerability within Garment, please send an email to [hello@clivern.com](mailto:hello@clivern.com) 142 | 143 | 144 | ## Contributing 145 | 146 | We are an open source, community-driven project so please feel free to join us. see the [contributing guidelines](CONTRIBUTING.md) for more details. 147 | 148 | 149 | ## License 150 | 151 | © 2021, Clivern. Released under [MIT License](https://opensource.org/licenses/mit-license.php). 152 | 153 | **Garment** is authored and maintained by [@Clivern](http://github.com/Clivern). 154 | -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Norwik/Garment/106385d746876183f218427d5becc947dd9b110d/assets/logo.png -------------------------------------------------------------------------------- /bin/release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Fetch latest version 4 | export LATEST_VERSION=$(curl --silent "https://api.github.com/repos/norwik/garment/releases/latest" | jq '.tag_name' | sed -E 's/.*"([^"]+)".*/\1/') 5 | 6 | # Update go checksum database (sum.golang.org) immediately after release 7 | curl --silent https://sum.golang.org/lookup/github.com/norwik/garment@{$LATEST_VERSION} 8 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | ignoreGeneratedHeader = false 2 | severity = "warning" 3 | confidence = 0.8 4 | errorCode = 0 5 | warningCode = 0 6 | 7 | [rule.blank-imports] 8 | [rule.context-as-argument] 9 | [rule.context-keys-type] 10 | [rule.dot-imports] 11 | [rule.error-return] 12 | [rule.error-strings] 13 | [rule.error-naming] 14 | [rule.exported] 15 | [rule.if-return] 16 | [rule.increment-decrement] 17 | [rule.var-naming] 18 | [rule.var-declaration] 19 | [rule.package-comments] 20 | [rule.range] 21 | [rule.receiver-naming] 22 | [rule.time-naming] 23 | [rule.unexported-return] 24 | [rule.indent-error-flow] 25 | [rule.errorf] 26 | [rule.empty-block] 27 | [rule.superfluous-else] 28 | [rule.unused-parameter] 29 | [rule.unreachable-code] 30 | [rule.redefines-builtin-id] -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/norwik/garment 2 | 3 | go 1.19 4 | 5 | require github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf h1:NrF81UtW8gG2LBGkXFQFqlfNnvMt9WdB46sfdJY4oqc= 2 | github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= 3 | -------------------------------------------------------------------------------- /pool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package garment 6 | 7 | import ( 8 | "fmt" 9 | "sync" 10 | ) 11 | 12 | var ( 13 | // pool var 14 | pool *Pool 15 | // once var 16 | once sync.Once 17 | ) 18 | 19 | // PingCallback type 20 | type PingCallback func(interface{}) error 21 | 22 | // CloseCallback type 23 | type CloseCallback func(interface{}) error 24 | 25 | // ReconnectCallback type 26 | type ReconnectCallback func(interface{}) error 27 | 28 | // Connection type 29 | type Connection struct { 30 | Value interface{} 31 | Ping PingCallback 32 | Close CloseCallback 33 | Reconnect ReconnectCallback 34 | } 35 | 36 | // Pool type 37 | type Pool struct { 38 | sync.RWMutex 39 | 40 | items map[string]Connection 41 | } 42 | 43 | // NewPool creates a new instance of Pool 44 | func NewPool() *Pool { 45 | once.Do(func() { 46 | pool = &Pool{ 47 | items: make(map[string]Connection), 48 | } 49 | }) 50 | 51 | return pool 52 | } 53 | 54 | // Get gets a connection with a key 55 | func (c *Pool) Get(key string) interface{} { 56 | c.Lock() 57 | defer c.Unlock() 58 | 59 | connection, ok := c.items[key] 60 | 61 | if !ok { 62 | return nil 63 | } 64 | 65 | return connection.Value 66 | } 67 | 68 | // Has checks if connection exists 69 | func (c *Pool) Has(key string) bool { 70 | if val := c.Get(key); val != nil { 71 | return true 72 | } 73 | 74 | return false 75 | } 76 | 77 | // Set sets a connection with a key 78 | func (c *Pool) Set(key string, value interface{}, ping PingCallback, close CloseCallback, reconnect ReconnectCallback) { 79 | c.Lock() 80 | defer c.Unlock() 81 | 82 | c.items[key] = Connection{ 83 | Value: value, 84 | Ping: ping, 85 | Close: close, 86 | Reconnect: reconnect, 87 | } 88 | } 89 | 90 | // Close close the connection and removes the key 91 | func (c *Pool) Close(key string) error { 92 | c.Lock() 93 | defer c.Unlock() 94 | 95 | connection, ok := c.items[key] 96 | 97 | if !ok { 98 | return fmt.Errorf("Unable to find %s", key) 99 | } 100 | 101 | return connection.Close(connection.Value) 102 | } 103 | 104 | // Ping checks the connection status 105 | func (c *Pool) Ping(key string) error { 106 | c.Lock() 107 | defer c.Unlock() 108 | 109 | connection, ok := c.items[key] 110 | 111 | if !ok { 112 | return fmt.Errorf("Unable to find %s", key) 113 | } 114 | 115 | return connection.Ping(connection.Value) 116 | } 117 | 118 | // Reconnect reconnects again 119 | func (c *Pool) Reconnect(key string) error { 120 | c.Lock() 121 | defer c.Unlock() 122 | 123 | connection, ok := c.items[key] 124 | 125 | if !ok { 126 | return fmt.Errorf("Unable to find %s", key) 127 | } 128 | 129 | return connection.Reconnect(connection.Value) 130 | } 131 | 132 | // Remove removes a connection 133 | func (c *Pool) Remove(key string) { 134 | c.Lock() 135 | defer c.Unlock() 136 | 137 | _, ok := c.items[key] 138 | 139 | if !ok { 140 | return 141 | } 142 | 143 | delete(c.items, key) 144 | } 145 | 146 | // Count counts the number of managed connections 147 | func (c *Pool) Count() int { 148 | c.Lock() 149 | defer c.Unlock() 150 | 151 | return len(c.items) 152 | } 153 | -------------------------------------------------------------------------------- /pool_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Clivern. All rights reserved. 2 | // Use of this source code is governed by the MIT 3 | // license that can be found in the LICENSE file. 4 | 5 | package garment 6 | 7 | import ( 8 | "errors" 9 | "testing" 10 | 11 | "github.com/franela/goblin" 12 | ) 13 | 14 | type DatabaseClient struct { 15 | Connection int 16 | } 17 | 18 | func (d *DatabaseClient) Execute() int { 19 | return d.Connection 20 | } 21 | 22 | func (d *DatabaseClient) Terminate() { 23 | d.Connection = 0 24 | } 25 | 26 | func (d *DatabaseClient) Close() { 27 | d.Connection = 0 28 | } 29 | 30 | func (d *DatabaseClient) Reconnect() { 31 | d.Connection = 1 32 | } 33 | 34 | func (d *DatabaseClient) Ping() bool { 35 | if d.Connection == 1 { 36 | return true 37 | } 38 | 39 | return false 40 | } 41 | 42 | // TestUnitPool test cases 43 | func TestUnitPool(t *testing.T) { 44 | g := goblin.Goblin(t) 45 | 46 | g.Describe("#Pool", func() { 47 | g.It("It should satisfy all provided test cases", func() { 48 | pool1 := NewPool() 49 | pool2 := NewPool() 50 | 51 | g.Assert(pool1.Count()).Equal(0) 52 | g.Assert(pool2.Count()).Equal(0) 53 | 54 | ping := func(con interface{}) error { 55 | if con.(*DatabaseClient).Ping() { 56 | return nil 57 | } 58 | 59 | return errors.New("DB connection is lost") 60 | } 61 | 62 | close := func(con interface{}) error { 63 | con.(*DatabaseClient).Close() 64 | 65 | return nil 66 | } 67 | 68 | reconnect := func(con interface{}) error { 69 | con.(*DatabaseClient).Reconnect() 70 | 71 | return nil 72 | } 73 | 74 | pool1.Set("db", &DatabaseClient{Connection: 1}, ping, close, reconnect) 75 | 76 | // Concurrent Access 77 | go func() { 78 | for i := 0; i < 100; i++ { 79 | if pool1.Has("db") && pool1.Ping("db") == nil { 80 | g.Assert(pool1.Get("db").(*DatabaseClient).Execute()).Equal(1) 81 | } 82 | } 83 | }() 84 | 85 | go func() { 86 | for i := 0; i < 100; i++ { 87 | if pool1.Has("db") && pool1.Ping("db") == nil { 88 | g.Assert(pool1.Get("db").(*DatabaseClient).Execute()).Equal(1) 89 | } 90 | } 91 | }() 92 | 93 | g.Assert(pool1.Count()).Equal(1) 94 | g.Assert(pool2.Count()).Equal(1) 95 | 96 | g.Assert(pool1.Has("db")).Equal(true) 97 | g.Assert(pool2.Has("db")).Equal(true) 98 | 99 | g.Assert(pool1.Has("db1")).Equal(false) 100 | g.Assert(pool2.Has("db1")).Equal(false) 101 | 102 | g.Assert(pool1.Get("db").(*DatabaseClient).Execute()).Equal(1) 103 | g.Assert(pool2.Get("db").(*DatabaseClient).Execute()).Equal(1) 104 | 105 | // Terminate Connection 106 | pool2.Get("db").(*DatabaseClient).Terminate() 107 | g.Assert(pool1.Get("db").(*DatabaseClient).Execute()).Equal(0) 108 | pool1.Reconnect("db") 109 | g.Assert(pool1.Get("db").(*DatabaseClient).Execute()).Equal(1) 110 | pool2.Remove("db") 111 | pool1.Reconnect("db") 112 | pool2.Remove("db") 113 | pool2.Ping("db") 114 | 115 | g.Assert(pool1.Has("db")).Equal(false) 116 | g.Assert(pool2.Has("db")).Equal(false) 117 | 118 | g.Assert(pool1.Count()).Equal(0) 119 | g.Assert(pool2.Count()).Equal(0) 120 | 121 | pool2.Set("db", &DatabaseClient{Connection: 1}, ping, close, reconnect) 122 | 123 | g.Assert(pool1.Count()).Equal(1) 124 | g.Assert(pool2.Count()).Equal(1) 125 | 126 | g.Assert(pool1.Ping("db") == nil).Equal(true) 127 | g.Assert(pool2.Ping("db") == nil).Equal(true) 128 | 129 | pool1.Close("db") 130 | pool1.Close("db1") 131 | 132 | g.Assert(pool1.Ping("db") == nil).Equal(false) 133 | g.Assert(pool2.Ping("db") == nil).Equal(false) 134 | 135 | g.Assert(pool1.Count()).Equal(1) 136 | g.Assert(pool2.Count()).Equal(1) 137 | }) 138 | }) 139 | } 140 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /techstack.md: -------------------------------------------------------------------------------- 1 | 26 |
27 | 28 | # Tech Stack File 29 | ![](https://img.stackshare.io/repo.svg "repo") [Norwik/Garment](https://github.com/Norwik/Garment)![](https://img.stackshare.io/public_badge.svg "public") 30 |

31 | |5
Tools used|12/21/23
Report generated| 32 | |------|------| 33 |
34 | 35 | ## Languages (1) 36 | 37 | 44 | 45 | 46 |
38 | Golang 39 |
40 | Golang 41 |
42 | 43 |
47 | 48 | ## DevOps (2) 49 | 50 | 57 | 58 | 65 | 66 | 67 |
51 | Git 52 |
53 | Git 54 |
55 | 56 |
59 | GitHub Actions 60 |
61 | GitHub Actions 62 |
63 | 64 |
68 | 69 | ## Other (1) 70 | 71 | 78 | 79 | 80 |
72 | Shell 73 |
74 | Shell 75 |
76 | 77 |
81 | 82 | 83 | ## Open source packages (1) 84 | 85 | ## Go Packages (1) 86 | 87 | |NAME|VERSION|LAST UPDATED|LAST UPDATED BY|LICENSE|VULNERABILITIES| 88 | |:------|:------|:------|:------|:------|:------| 89 | |[goblin](https://pkg.go.dev/github.com/franela/goblin)|v0.0.0|06/26/22|renovate[bot] |MIT|N/A| 90 | 91 |
92 |
93 | 94 | Generated via [Stack File](https://github.com/marketplace/stack-file) 95 | -------------------------------------------------------------------------------- /techstack.yml: -------------------------------------------------------------------------------- 1 | repo_name: Norwik/Garment 2 | report_id: f5293acf9ae60108ce94c074d9dc07e4 3 | version: 0.1 4 | repo_type: Public 5 | timestamp: '2023-12-21T15:24:24+00:00' 6 | requested_by: Clivern 7 | provider: github 8 | branch: main 9 | detected_tools_count: 5 10 | tools: 11 | - name: Golang 12 | description: An open source programming language that makes it easy to build simple, 13 | reliable, and efficient software 14 | website_url: http://golang.org/ 15 | license: BSD-3-Clause 16 | open_source: true 17 | hosted_saas: false 18 | category: Languages & Frameworks 19 | sub_category: Languages 20 | image_url: https://img.stackshare.io/service/1005/O6AczwfV_400x400.png 21 | detection_source: Repo Metadata 22 | - name: Git 23 | description: Fast, scalable, distributed revision control system 24 | website_url: http://git-scm.com/ 25 | open_source: true 26 | hosted_saas: false 27 | category: Build, Test, Deploy 28 | sub_category: Version Control System 29 | image_url: https://img.stackshare.io/service/1046/git.png 30 | detection_source: Repo Metadata 31 | - name: GitHub Actions 32 | description: Automate your workflow from idea to production 33 | website_url: https://github.com/features/actions 34 | open_source: false 35 | hosted_saas: true 36 | category: Build, Test, Deploy 37 | sub_category: Continuous Integration 38 | image_url: https://img.stackshare.io/service/11563/actions.png 39 | detection_source: ".github/workflows/build.yml" 40 | last_updated_by: renovate[bot] 41 | last_updated_on: 2022-06-27 11:13:39.000000000 Z 42 | - name: Shell 43 | description: A shell is a text-based terminal, used for manipulating programs and 44 | files. Shell scripts typically manage program execution. 45 | website_url: https://en.wikipedia.org/wiki/Shell_script 46 | open_source: false 47 | hosted_saas: false 48 | category: Languages & Frameworks 49 | sub_category: Languages 50 | image_url: https://img.stackshare.io/service/4631/default_c2062d40130562bdc836c13dbca02d318205a962.png 51 | detection_source: Repo Metadata 52 | - name: goblin 53 | description: Minimal and Beautiful Go testing framework 54 | package_url: https://pkg.go.dev/github.com/franela/goblin 55 | version: 0.0.0 56 | license: MIT 57 | open_source: true 58 | hosted_saas: false 59 | category: Libraries 60 | sub_category: Go Modules Packages 61 | image_url: https://img.stackshare.io/package/go-packages/image.png 62 | detection_source_url: https://github.com/Norwik/Garment/blob/main/go.sum 63 | detection_source: go.mod 64 | last_updated_by: renovate[bot] 65 | last_updated_on: 2022-06-26 22:36:44.000000000 Z 66 | --------------------------------------------------------------------------------