├── src ├── k8s │ ├── .gitignore │ ├── demo-flux │ │ ├── clusters │ │ │ ├── production │ │ │ │ └── .gitkeep │ │ │ ├── staging │ │ │ │ ├── flux-system │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── gotk-sync.yaml │ │ │ │ └── apps.yaml │ │ │ └── development │ │ │ │ ├── flux-system │ │ │ │ ├── kustomization.yaml │ │ │ │ └── gotk-sync.yaml │ │ │ │ ├── sources.yaml │ │ │ │ ├── apps.yaml │ │ │ │ └── infrastructure.yaml │ │ ├── apps │ │ │ ├── base │ │ │ │ ├── calculator │ │ │ │ │ ├── namespace.yaml │ │ │ │ │ ├── configMap.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ ├── virtualService.yaml │ │ │ │ │ ├── canary.yaml │ │ │ │ │ └── deployment.yaml │ │ │ │ ├── redis-cache │ │ │ │ │ ├── namespace.yaml │ │ │ │ │ ├── service.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── deployment.yaml │ │ │ │ └── postgresql-core │ │ │ │ │ ├── helmRepository.yaml │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── helmRelease.yaml │ │ │ └── overlays │ │ │ │ ├── production │ │ │ │ └── calculator │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── configMap.yaml │ │ │ │ └── staging │ │ │ │ └── calculator │ │ │ │ ├── kustomization.yaml │ │ │ │ └── configMap.yaml │ │ └── infrastructure │ │ │ └── base │ │ │ ├── flagger │ │ │ ├── namespace.yaml │ │ │ ├── helmRepository.yaml │ │ │ ├── kustomization.yaml │ │ │ └── helmRelease.yaml │ │ │ ├── datadog │ │ │ ├── namespace.yaml │ │ │ ├── helmRepository.yaml │ │ │ ├── kustomization.yaml │ │ │ └── helmRelease.yaml │ │ │ ├── gloo-system │ │ │ ├── namespace.yaml │ │ │ ├── deployment.yaml │ │ │ ├── helmRepository.yaml │ │ │ ├── gateway.yaml │ │ │ ├── upstreams.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── virtualServices.yaml │ │ │ ├── helmRelease.yaml │ │ │ └── settings.yaml │ │ │ ├── centralized-log │ │ │ ├── namespace.yaml │ │ │ ├── kibana.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── elasticsearch.yaml │ │ │ ├── logstash.yaml │ │ │ └── beat.yaml │ │ │ └── elastic-system │ │ │ └── kustomization.yaml │ ├── demo-kustomization │ │ ├── overlays │ │ │ ├── staging │ │ │ │ ├── redis-cache │ │ │ │ │ └── kustomization.yaml │ │ │ │ └── calculator │ │ │ │ │ ├── kustomization.yaml │ │ │ │ │ └── configMap.yaml │ │ │ └── production │ │ │ │ ├── calculator │ │ │ │ ├── configMap.yaml │ │ │ │ ├── deployment.yaml │ │ │ │ └── kustomization.yaml │ │ │ │ └── redis-cache │ │ │ │ ├── kustomization.yaml │ │ │ │ └── values.yaml │ │ └── base │ │ │ ├── calculator │ │ │ ├── configMap.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── service.yaml │ │ │ └── deployment.yaml │ │ │ ├── postgresql-core │ │ │ ├── helmRepository.yaml │ │ │ ├── kustomization.yaml │ │ │ └── helmRelease.yaml │ │ │ └── redis-cache │ │ │ ├── kustomization.yaml │ │ │ └── values.yaml │ └── demo-helm │ │ └── charts │ │ └── calculator │ │ ├── values.yaml │ │ ├── templates │ │ ├── configmap.yaml │ │ ├── service.yaml │ │ └── deployment.yaml │ │ ├── .helmignore │ │ └── Chart.yaml ├── etc │ ├── demo-kong-plugin │ │ ├── pkg │ │ │ └── .gitkeep │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── internal │ │ │ ├── domain │ │ │ │ ├── entity │ │ │ │ │ └── keychecker │ │ │ │ │ │ ├── validate_key_input.go │ │ │ │ │ │ └── errors.go │ │ │ │ ├── repo │ │ │ │ │ └── token_repository.go │ │ │ │ └── usecase │ │ │ │ │ └── keychecker │ │ │ │ │ ├── get_token_use_case.go │ │ │ │ │ └── validate_key_use_case.go │ │ │ ├── di │ │ │ │ ├── app_module.go │ │ │ │ ├── repo_module.go │ │ │ │ └── usecase_module.go │ │ │ ├── data │ │ │ │ └── token_repository.go │ │ │ └── delivery │ │ │ │ └── kong │ │ │ │ └── key_checker.go │ │ ├── Dockerfile │ │ ├── scripts │ │ │ └── start-development.sh │ │ ├── config.yml │ │ ├── cmd │ │ │ └── kong │ │ │ │ └── keychecker │ │ │ │ └── main.go │ │ ├── go.mod │ │ ├── README.md │ │ ├── docker-compose.yml │ │ └── go.sum │ ├── demo-nats │ │ ├── .gitignore │ │ ├── go.mod │ │ ├── pubsub │ │ │ ├── publisher │ │ │ │ └── main.go │ │ │ └── consumer │ │ │ │ └── main.go │ │ ├── go.sum │ │ └── docker-compose.yaml │ ├── demo-oauth2 │ │ ├── .gitignore │ │ ├── internal │ │ │ ├── auth │ │ │ │ ├── types.go │ │ │ │ ├── clients.go │ │ │ │ ├── repositories.go │ │ │ │ └── handlers.go │ │ │ └── pokedex │ │ │ │ ├── clients.go │ │ │ │ └── handlers.go │ │ ├── docker-compose.yaml │ │ ├── go.mod │ │ └── cmd │ │ │ ├── pokedex │ │ │ └── main.go │ │ │ └── auth │ │ │ └── main.go │ ├── demo-event-sourcing │ │ ├── .gitignore │ │ ├── go.mod │ │ ├── go.sum │ │ ├── internal │ │ │ ├── domain │ │ │ │ ├── communication │ │ │ │ │ └── service.go │ │ │ │ ├── task │ │ │ │ │ ├── repository.go │ │ │ │ │ ├── events.go │ │ │ │ │ └── task.go │ │ │ │ ├── types.go │ │ │ │ └── report │ │ │ │ │ ├── repository.go │ │ │ │ │ └── report.go │ │ │ ├── infrastructure │ │ │ │ ├── service │ │ │ │ │ └── service.go │ │ │ │ └── repository │ │ │ │ │ └── task_repository.go │ │ │ └── application │ │ │ │ ├── projection_handler.go │ │ │ │ └── command_handler.go │ │ └── cmd │ │ │ └── todo │ │ │ └── main.go │ ├── XAAM │ │ ├── .env │ │ ├── .test.env │ │ ├── internal │ │ │ ├── domain │ │ │ │ ├── entity │ │ │ │ │ ├── resource.go │ │ │ │ │ ├── action.go │ │ │ │ │ ├── business │ │ │ │ │ │ └── get_one_response.go │ │ │ │ │ ├── auth │ │ │ │ │ │ ├── find_resources_by_compliance_request.go │ │ │ │ │ │ ├── check_response.go │ │ │ │ │ │ └── check_request.go │ │ │ │ │ ├── target_resource_action.go │ │ │ │ │ └── errors.go │ │ │ │ ├── repo │ │ │ │ │ ├── business_repo.go │ │ │ │ │ ├── resource_action_repo.go │ │ │ │ │ └── resource_repo.go │ │ │ │ └── usecase │ │ │ │ │ ├── business │ │ │ │ │ └── find_one_by_business_id_use_case.go │ │ │ │ │ └── auth │ │ │ │ │ ├── find_resources_by_compliance_use_case.go │ │ │ │ │ └── find_resources_by_compliance_use_case_test.go │ │ │ ├── delivery │ │ │ │ ├── ping_handler.go │ │ │ │ ├── utils.go │ │ │ │ └── auth_check_handler.go │ │ │ ├── source │ │ │ │ ├── business_repo.go │ │ │ │ ├── resource_action_repo.go │ │ │ │ └── resource_repo.go │ │ │ ├── di │ │ │ │ └── di.go │ │ │ └── mock │ │ │ │ └── domain │ │ │ │ └── repo │ │ │ │ ├── business_repo.go │ │ │ │ ├── policy_repo.go │ │ │ │ └── resource_repo.go │ │ ├── pkg │ │ │ └── slices │ │ │ │ └── slices.go │ │ ├── docker-compose.yaml │ │ ├── e2e │ │ │ ├── ping_test.go │ │ │ └── api_v1_authotrisation_check_test.go │ │ ├── cmd │ │ │ └── http │ │ │ │ └── main.go │ │ ├── go.mod │ │ └── files │ │ │ └── sql │ │ │ ├── 0001.sql │ │ │ └── 0002.sql │ ├── demo-unit-test │ │ ├── internal │ │ │ ├── article │ │ │ │ ├── delivery.go │ │ │ │ ├── repo.go │ │ │ │ ├── entity.go │ │ │ │ └── usecase.go │ │ │ └── user │ │ │ │ ├── usecase.go │ │ │ │ ├── entity.go │ │ │ │ ├── delivery.go │ │ │ │ ├── repo.go │ │ │ │ ├── usecase_mock_test.go │ │ │ │ ├── repo_test.go │ │ │ │ ├── usecase_test.go │ │ │ │ ├── delivery_test.go │ │ │ │ └── repo_mock_test.go │ │ ├── pkg │ │ │ └── calc │ │ │ │ ├── calc.go │ │ │ │ └── calc_test.go │ │ ├── go.mod │ │ ├── usecase_test.go │ │ └── go.sum │ ├── clean-arch-ddd-cqrs-es │ │ ├── go.mod │ │ ├── internal │ │ │ ├── infrastructure │ │ │ │ └── times │ │ │ │ │ └── datetime.go │ │ │ └── domain │ │ │ │ ├── user │ │ │ │ ├── error_code.go │ │ │ │ └── user.go │ │ │ │ ├── error.go │ │ │ │ └── task │ │ │ │ ├── error_code.go │ │ │ │ └── task.go │ │ └── pkg │ │ │ └── errr │ │ │ └── errr.go │ ├── demo-redlock │ │ ├── go.mod │ │ ├── docker-compose.yml │ │ ├── example │ │ │ └── main.go │ │ └── redlock.go │ ├── kafka │ │ ├── go.mod │ │ ├── basic │ │ │ ├── publisher │ │ │ │ └── main.go │ │ │ └── consumer │ │ │ │ └── main.go │ │ ├── docker-compose.yml │ │ └── go.sum │ └── go-calculator │ │ ├── Dockerfile │ │ ├── go.mod │ │ └── cmd.go ├── concurrency │ ├── workerpool │ │ ├── types.go │ │ ├── example │ │ │ └── main.go │ │ └── worker_pool.go │ ├── semaphore │ │ ├── semaphore.go │ │ └── example │ │ │ └── main.go │ └── pipeline │ │ ├── example │ │ ├── e01 │ │ │ └── main.go │ │ ├── util.go │ │ ├── e02 │ │ │ └── main.go │ │ ├── e00 │ │ │ └── main.go │ │ ├── e03 │ │ │ └── main.go │ │ └── e04 │ │ │ └── main.go │ │ ├── pipeline_test.go │ │ ├── pipeline.go │ │ └── pipeline_bench_test.go ├── datastructure │ ├── types │ │ ├── generic.go │ │ └── func.go │ ├── stack │ │ └── stack.go │ ├── binarytree │ │ └── binarytree.go │ ├── hashmap │ │ └── hashmap.go │ ├── linkedlist │ │ ├── example │ │ │ └── main.go │ │ ├── linkedlist.go │ │ └── linkedlist_test.go │ └── queue │ │ ├── queue.go │ │ └── queue_test.go └── distributed │ └── semaphore │ ├── go.mod │ ├── go.sum │ ├── example │ └── main.go │ └── semaphore.go ├── .gitignore └── README.md /src/k8s/.gitignore: -------------------------------------------------------------------------------- 1 | charts 2 | .env -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/pkg/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/etc/demo-nats/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/production/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | vendor -------------------------------------------------------------------------------- /src/etc/demo-oauth2/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | volumes/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/playground.go 2 | .DS_Store 3 | .vscode 4 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | tmp/ -------------------------------------------------------------------------------- /src/etc/XAAM/.env: -------------------------------------------------------------------------------- 1 | DB_NAME=xaam 2 | DB_USER=root 3 | DB_PASSWORD=root -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/article/delivery.go: -------------------------------------------------------------------------------- 1 | package article 2 | -------------------------------------------------------------------------------- /src/etc/XAAM/.test.env: -------------------------------------------------------------------------------- 1 | DB_NAME=xaam_test 2 | DB_USER=root 3 | DB_PASSWORD=root -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/clean-arch-ddd-cqrs-es 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: calculator -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/redis-cache/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: redis-cache -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/flagger/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: flagger -------------------------------------------------------------------------------- /src/concurrency/workerpool/types.go: -------------------------------------------------------------------------------- 1 | package workerpool 2 | 3 | // T is a type alias to accept any type. 4 | type T = interface{} 5 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/datadog/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: calculator -------------------------------------------------------------------------------- /src/datastructure/types/generic.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type T interface{} 4 | 5 | type U interface{} 6 | 7 | type V interface{} 8 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/resource.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type Resource struct { 4 | ID int64 5 | Name string 6 | } 7 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-es 2 | 3 | go 1.20 4 | 5 | require github.com/google/uuid v1.6.0 6 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: gloo-system -------------------------------------------------------------------------------- /src/etc/demo-redlock/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-redlock 2 | 3 | go 1.15 4 | 5 | require github.com/go-redis/redis/v8 v8.9.0 6 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/staging/redis-cache/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/redis-cache 3 | namePrefix: staging- -------------------------------------------------------------------------------- /src/etc/kafka/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/go-exercise/src/etc/kafka 2 | 3 | go 1.15 4 | 5 | require github.com/segmentio/kafka-go v0.4.25 6 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/centralized-log/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: centralized-log -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | data: 6 | max_number: "100" 7 | -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/internal/infrastructure/times/datetime.go: -------------------------------------------------------------------------------- 1 | package times 2 | 3 | import "time" 4 | 5 | type TimeProvider interface { 6 | Now() time.Time 7 | } 8 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/overlays/production/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/calculator 3 | namePrefix: staging- 4 | patches: 5 | - path: configMap.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/overlays/staging/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/calculator 3 | namePrefix: staging- 4 | patches: 5 | - path: configMap.yaml -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/staging/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/calculator 3 | namePrefix: staging- 4 | patches: 5 | - path: configMap.yaml -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | 3 | all: key-checker 4 | 5 | key-checker: cmd/kong/keychecker/main.go 6 | go build -o bin/key-checker cmd/kong/keychecker/main.go 7 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/pkg/calc/calc.go: -------------------------------------------------------------------------------- 1 | package calc 2 | 3 | func Factorial(n uint) uint { 4 | if n <= 1 { 5 | return 1 6 | } 7 | 8 | return n * Factorial(n-1) 9 | } 10 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/overlays/production/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | data: 6 | max_number: "75" 7 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/staging/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | data: 6 | max_number: "75" 7 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/domain/entity/keychecker/validate_key_input.go: -------------------------------------------------------------------------------- 1 | package keychecker 2 | 3 | type ValidateKeyInput struct { 4 | GivenKey string 5 | ValidKey string 6 | } 7 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/elastic-system/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - crds.yaml 5 | - operator.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: gateway-proxy 5 | namespace: gloo-system 6 | spec: {} 7 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/production/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | data: 6 | max_number: "666" 7 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/production/calculator/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: calculator-deployment 5 | spec: 6 | replicas: 5 -------------------------------------------------------------------------------- /src/datastructure/stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "github.com/syafdia/go-exercise/src/datastructure/types" 4 | 5 | type Stack interface { 6 | Pop() types.T 7 | Push(v types.T) 8 | } 9 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | namespace: calculator 6 | data: 7 | max_number: "100" 8 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/staging/flux-system/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - gotk-components.yaml 5 | - gotk-sync.yaml 6 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 2 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 3 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/development/flux-system/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - gotk-components.yaml 5 | - gotk-sync.yaml 6 | -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for go-calculator. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | maxNumber: 50 6 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/action.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type Action struct { 4 | ID int64 `db:"id"` 5 | ResourceID int64 `db:"resource_id"` 6 | Name string `db:"name"` 7 | } 8 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/overlays/staging/calculator/configMap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: calculator-configmap 5 | namespace: calculator 6 | data: 7 | max_number: "75" 8 | -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ .Release.Name }}-configmap 5 | data: 6 | max_number: {{ .Values.maxNumber | quote }} 7 | -------------------------------------------------------------------------------- /src/datastructure/binarytree/binarytree.go: -------------------------------------------------------------------------------- 1 | package binarytree 2 | 3 | import "github.com/syafdia/go-exercise/src/datastructure/types" 4 | 5 | type BinaryTree interface { 6 | Left() types.T 7 | Right() types.T 8 | } 9 | -------------------------------------------------------------------------------- /src/datastructure/hashmap/hashmap.go: -------------------------------------------------------------------------------- 1 | package hashmap 2 | 3 | import "github.com/syafdia/go-exercise/src/datastructure/types" 4 | 5 | type HashMap interface { 6 | Set(k types.T, v types.U) 7 | Get(k types.T) 8 | } 9 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/production/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/calculator 3 | namePrefix: production- 4 | patches: 5 | - path: configMap.yaml 6 | - path: deployment.yaml -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/business/get_one_response.go: -------------------------------------------------------------------------------- 1 | package business 2 | 3 | type GetOneResponse struct { 4 | BusinessID string 5 | CountryID string 6 | IndustryID int64 7 | LegalEntityID int64 8 | } 9 | -------------------------------------------------------------------------------- /src/etc/XAAM/pkg/slices/slices.go: -------------------------------------------------------------------------------- 1 | package slices 2 | 3 | func ContainsStr(xs []string, s string) bool { 4 | for _, x := range xs { 5 | if x == s { 6 | return true 7 | } 8 | } 9 | 10 | return false 11 | } 12 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/auth/find_resources_by_compliance_request.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | type FindResourcesByComplianceRequest struct { 4 | IndustryID int64 5 | LegalEntityID int64 6 | Resources []string 7 | } 8 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build plugin. 2 | FROM kong/go-plugin-tool:2.0.4-alpine-latest 3 | 4 | ENV BUILD_DIR /tmp/go-plugins/ 5 | 6 | WORKDIR $BUILD_DIR 7 | 8 | COPY . . 9 | RUN apk add make 10 | RUN make all 11 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-unit-test 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/DATA-DOG/go-sqlmock v1.5.0 7 | github.com/golang/mock v1.6.0 8 | github.com/jmoiron/sqlx v1.3.4 9 | ) 10 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/datadog/helmRepository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: HelmRepository 3 | metadata: 4 | name: datadog-helm-repository 5 | spec: 6 | interval: 5m 7 | url: https://helm.datadoghq.com 8 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/delivery/ping_handler.go: -------------------------------------------------------------------------------- 1 | package delivery 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | func GetPingHandler() gin.HandlerFunc { 6 | return func(c *gin.Context) { 7 | c.JSON(200, gin.H{"message": "pong"}) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/domain/entity/keychecker/errors.go: -------------------------------------------------------------------------------- 1 | package keychecker 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | ErrKeyEmpty = errors.New("key is empty") 9 | ErrKeyNotValid = errors.New("key is not valid") 10 | ) 11 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/postgresql-core/helmRepository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: HelmRepository 3 | metadata: 4 | name: bitnami-helm-repository 5 | spec: 6 | interval: 5m 7 | url: https://charts.bitnami.com/bitnami 8 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/auth/types.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrNotFound = errors.New("data is not found") 7 | ) 8 | 9 | type User struct { 10 | ID string 11 | Username string 12 | Password string 13 | } 14 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/postgresql-core/helmRepository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: HelmRepository 3 | metadata: 4 | name: bitnami-helm-repository 5 | spec: 6 | interval: 5m 7 | url: https://charts.bitnami.com/bitnami 8 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/production/redis-cache/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../../base/redis-cache 3 | namePrefix: production- 4 | # helmCharts: 5 | # - name: redis 6 | # repo: https://charts.bitnami.com/bitnami 7 | # valuesFile: values.yaml -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/communication/service.go: -------------------------------------------------------------------------------- 1 | package communication 2 | 3 | import "context" 4 | 5 | type EmailMessage = string 6 | 7 | type EmailService interface { 8 | SendEmail(ctx context.Context, message EmailMessage) 9 | } 10 | -------------------------------------------------------------------------------- /src/datastructure/types/func.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type Func0 func(v T) 4 | 5 | type Func1 func(v T) U 6 | 7 | type Func2 func(v1 T, v2 U) V 8 | 9 | type Mapper func(v T) U 10 | 11 | type Filterrer func(v T) bool 12 | 13 | type Reducer func(acc U, v T) U 14 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/scripts/start-development.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Run docker 4 | docker-compose up -d 5 | 6 | # Hot Reload 7 | CompileDaemon \ 8 | -build='docker-compose exec -T kong-plugin-builder make all' \ 9 | -command='docker-compose exec -T kong kong reload' -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/flagger/helmRepository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: HelmRepository 3 | metadata: 4 | name: flagger-helm-repository 5 | namespace: flagger 6 | spec: 7 | interval: 10m 8 | url: https://flagger.app 9 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/domain/repo/token_repository.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import "context" 4 | 5 | type TokenRepository interface { 6 | ExchangeToken(ctx context.Context, key string) (string, error) 7 | Invalidate(ctx context.Context, token string) error 8 | } 9 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/postgresql-core/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: postgresql-core 5 | commonLabels: 6 | app: postgresql-core 7 | resources: 8 | - helmRepository.yaml 9 | - helmRelease.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/development/sources.yaml: -------------------------------------------------------------------------------- 1 | # apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | # kind: HelmRepository 3 | # metadata: 4 | # name: datadog-helm-repository 5 | # namespace: flux-system 6 | # spec: 7 | # interval: 5m 8 | # url: https://helm.datadoghq.com -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/postgresql-core/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: postgresql-core 5 | commonLabels: 6 | app: postgresql-core 7 | resources: 8 | - helmRepository.yaml 9 | - helmRelease.yaml -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/config.yml: -------------------------------------------------------------------------------- 1 | _format_version: '2.1' 2 | services: 3 | - name: mockbin-service-1 4 | url: http://mockbin.com/request 5 | routes: 6 | - paths: 7 | - '/' 8 | plugins: 9 | - name: key-checker 10 | config: 11 | api_key: mysecretconsumerkey 12 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/datadog/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: datadog 4 | metadata: 5 | name: datadog 6 | commonLabels: 7 | app: datadog 8 | resources: 9 | - namespace.yaml 10 | - helmRelease.yaml -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: kustomize.config.k8s.io/v1beta1 3 | kind: Kustomization 4 | metadata: 5 | name: calculator 6 | commonLabels: 7 | app: calculator 8 | resources: 9 | - deployment.yaml 10 | - service.yaml 11 | - configMap.yaml -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/calculator/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: calculator-service 5 | spec: 6 | selector: 7 | app: calculator 8 | type: LoadBalancer 9 | ports: 10 | - protocol: TCP 11 | port: 8080 12 | targetPort: 8080 -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/redis-cache/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: redis-service 5 | namespace: redis-cache 6 | spec: 7 | type: LoadBalancer 8 | selector: 9 | appName: redis-cache 10 | ports: 11 | - port: 6379 12 | targetPort: 6379 -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/helmRepository.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: source.toolkit.fluxcd.io/v1beta2 2 | kind: HelmRepository 3 | metadata: 4 | name: solo-helm-repository 5 | namespace: gloo-system 6 | spec: 7 | interval: 5m 8 | url: https://storage.googleapis.com/solo-public-helm -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/cmd/kong/keychecker/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/Kong/go-pdk/server" 5 | kongdelivery "github.com/syafdia/demo-kong-plugin/internal/delivery/kong" 6 | ) 7 | 8 | func main() { 9 | server.StartServer(kongdelivery.NewKeyChecker, "0.1", 0) 10 | } 11 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/centralized-log/kibana.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kibana.k8s.elastic.co/v1 2 | kind: Kibana 3 | metadata: 4 | name: centralized-log-kb 5 | namespace: centralized-log 6 | spec: 7 | version: 8.9.1 8 | count: 1 9 | elasticsearchRef: 10 | name: centralized-log-es -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/auth/check_response.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | type CheckResultResponse struct { 4 | Kind string `json:"kind"` 5 | Actions map[string]string `json:"actions"` 6 | } 7 | 8 | type CheckResponse struct { 9 | Results []CheckResultResponse `json:"results"` 10 | } 11 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/pokedex/clients.go: -------------------------------------------------------------------------------- 1 | package pokedex 2 | 3 | import "golang.org/x/oauth2" 4 | 5 | type Client struct { 6 | OAuth2 *oauth2.Config 7 | Pokemon interface{} 8 | } 9 | 10 | func NewClient(oauth2 *oauth2.Config) *Client { 11 | return &Client{ 12 | OAuth2: oauth2, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/redis-cache/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: redis-cache 4 | metadata: 5 | name: redis-cache 6 | commonLabels: 7 | app: redis-cache 8 | resources: 9 | - namespace.yaml 10 | - deployment.yaml 11 | - service.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/flagger/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: flagger 4 | metadata: 5 | name: flagger 6 | commonLabels: 7 | app: flagger 8 | resources: 9 | - namespace.yaml 10 | - helmRepository.yaml 11 | - helmRelease.yaml -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: {{ .Release.Name }}-service 5 | spec: 6 | selector: 7 | app: {{ .Release.Name }} 8 | type: LoadBalancer 9 | ports: 10 | - protocol: TCP 11 | port: 8080 12 | targetPort: 8080 -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/repo/business_repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "context" 5 | 6 | be "github.com/syafdia/xaam/internal/domain/entity/business" 7 | ) 8 | 9 | type BusinessRepo interface { 10 | FindOneByBusinessID(ctx context.Context, businessID string) (be.GetOneResponse, error) 11 | } 12 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: calculator-service 5 | namespace: calculator 6 | spec: 7 | type: LoadBalancer 8 | selector: 9 | appName: calculator 10 | ports: 11 | - protocol: TCP 12 | port: 8080 13 | targetPort: 8080 -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/article/repo.go: -------------------------------------------------------------------------------- 1 | package article 2 | 3 | import "context" 4 | 5 | type ArticleRepo interface { 6 | Create(ctx context.Context, input CreateArticleInput) (Article, error) 7 | FindOneByID(ctx context.Context, id int64) (Article, error) 8 | Destroy(ctx context.Context, id int64) error 9 | } 10 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/task/repository.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/syafdia/demo-es/internal/domain" 7 | ) 8 | 9 | type TaskRepository interface { 10 | Store(ctx context.Context, task Task) error 11 | Find(ctx context.Context, id domain.ID) (Task, error) 12 | } 13 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/types.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | type ID string 10 | 11 | func NewID() ID { 12 | return ID(uuid.New().String()) 13 | } 14 | 15 | type Event interface { 16 | AggregateID() ID 17 | OccuredAt() time.Time 18 | } 19 | -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/internal/domain/user/error_code.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import "github.com/syafdia/clean-arch-ddd-cqrs-es/internal/domain" 4 | 5 | const ( 6 | ErrCodeInvalidPasswordLength domain.ErrorCode = "USER-INVALID_PASSWORD_LENGTH" 7 | ErrCodeInvalidEmailFormat domain.ErrorCode = "USER-INVALID_EMAIL_FORMAT" 8 | ) 9 | -------------------------------------------------------------------------------- /src/etc/demo-redlock/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | redis-1: 5 | image: "redis:alpine" 6 | ports: 7 | - '7001:6379' 8 | redis-2: 9 | image: "redis:alpine" 10 | ports: 11 | - '7002:6379' 12 | redis-3: 13 | image: "redis:alpine" 14 | ports: 15 | - '7003:6379' 16 | 17 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/redis-cache/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | metadata: 4 | name: redis-cache 5 | commonLabels: 6 | app: redis-cache 7 | helmCharts: 8 | - name: redis 9 | repo: https://charts.bitnami.com/bitnami 10 | version: 7.0.11 11 | valuesFile: values.yaml -------------------------------------------------------------------------------- /src/distributed/semaphore/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/distributed/semaphore 2 | 3 | go 1.20 4 | 5 | require github.com/go-redis/redis/v8 v8.11.5 6 | 7 | require ( 8 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 9 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 10 | github.com/google/uuid v1.6.0 11 | ) 12 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/centralized-log/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: centralized-log 4 | metadata: 5 | name: centralized-log 6 | commonLabels: 7 | app: centralized-log 8 | resources: 9 | - namespace.yaml 10 | - elasticsearch.yaml 11 | - kibana.yaml 12 | - beat.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/gateway.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: gateway.solo.io/v1 2 | kind: Gateway 3 | metadata: 4 | name: gateway-proxy 5 | namespace: gloo-system 6 | 7 | spec: 8 | bindAddress: '::' 9 | bindPort: 8080 10 | httpGateway: {} 11 | proxyNames: 12 | - gateway-proxy 13 | ssl: false 14 | useProxyProto: false 15 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/staging/apps.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.toolkit.fluxcd.io/v1 2 | kind: Kustomization 3 | metadata: 4 | name: calculator 5 | namespace: flux-system 6 | spec: 7 | interval: 30s 8 | sourceRef: 9 | kind: GitRepository 10 | name: flux-system 11 | path: ./src/k8s/demo-flux/apps/overlays/staging/calculator 12 | prune: true -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/repo/resource_action_repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "context" 5 | 6 | e "github.com/syafdia/xaam/internal/domain/entity" 7 | ) 8 | 9 | type PolicyRepo interface { 10 | FindMultipleByIDandTargetType( 11 | ctx context.Context, 12 | targetID int64, 13 | targetType e.TargetType, 14 | ) ([]e.Action, error) 15 | } 16 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-kong-plugin 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/Kong/go-pdk v0.6.0 7 | github.com/fatih/color v1.10.0 // indirect 8 | github.com/fsnotify/fsnotify v1.4.9 // indirect 9 | github.com/githubnemo/CompileDaemon v1.2.1 // indirect 10 | github.com/pkg/errors v0.9.1 // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: calculator 4 | metadata: 5 | name: calculator 6 | commonLabels: 7 | app: calculator 8 | resources: 9 | - namespace.yaml 10 | - configMap.yaml 11 | - deployment.yaml 12 | - service.yaml 13 | - virtualService.yaml 14 | - canary.yaml -------------------------------------------------------------------------------- /src/datastructure/linkedlist/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/syafdia/go-exercise/src/datastructure/linkedlist" 7 | ) 8 | 9 | type Person struct { 10 | Name string 11 | Age int 12 | } 13 | 14 | func tryLinkedList() { 15 | 16 | } 17 | 18 | func main() { 19 | xs := linkedlist.New("H", "E", "L") 20 | fmt.Println(xs) 21 | } 22 | -------------------------------------------------------------------------------- /src/etc/XAAM/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | redis-xaam: 5 | image: "redis:alpine" 6 | ports: 7 | - '6379:6379' 8 | postgresql-xaam: 9 | image: "postgres:14.2-alpine" 10 | restart: always 11 | environment: 12 | POSTGRES_USER: root 13 | POSTGRES_PASSWORD: root 14 | POSTGRES_DB: xaam 15 | ports: 16 | - '5432:5432' -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/target_resource_action.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | type TargetType = string 4 | 5 | const ( 6 | TargetTypeLegalEntity TargetType = "legal_entity" 7 | TargetTypeIndustry TargetType = "industry" 8 | ) 9 | 10 | type TargetAction struct { 11 | ID int64 12 | ResourceID int64 13 | Name string 14 | TargetID int64 15 | TargetType TargetType 16 | } 17 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/article/entity.go: -------------------------------------------------------------------------------- 1 | package article 2 | 3 | type Article struct { 4 | ID int64 5 | Title string 6 | Body string 7 | UserID int64 8 | } 9 | 10 | type ArticleWithAuthor struct { 11 | Article 12 | UserFirstName string 13 | UserLastName string 14 | } 15 | 16 | type CreateArticleInput struct { 17 | Title string 18 | Body string 19 | UserID int64 20 | } 21 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/upstreams.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: gloo.solo.io/v1 3 | kind: Upstream 4 | metadata: 5 | name: auth-server-upstream 6 | namespace: gloo-system 7 | spec: 8 | discoveryMetadata: {} 9 | kube: 10 | selector: 11 | app: auth-server 12 | serviceName: auth-server-service 13 | serviceNamespace: gloo-system 14 | servicePort: 8000 15 | --- -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/pkg/errr/errr.go: -------------------------------------------------------------------------------- 1 | package errr 2 | 3 | type Err struct { 4 | code string 5 | message string 6 | } 7 | 8 | func NewErr(code string, message string) *Err { 9 | return &Err{ 10 | code: code, 11 | message: message, 12 | } 13 | } 14 | 15 | func (e *Err) GetCode() string { 16 | return e.code 17 | } 18 | 19 | func (e *Err) Error() string { 20 | return e.message 21 | } 22 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/centralized-log/elasticsearch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: elasticsearch.k8s.elastic.co/v1 2 | kind: Elasticsearch 3 | metadata: 4 | name: centralized-log-es 5 | namespace: centralized-log 6 | spec: 7 | version: 8.9.1 8 | nodeSets: 9 | - name: default-nodes 10 | count: 1 11 | config: 12 | node.roles: ["master", "data", "ingest"] 13 | node.store.allow_mmap: false -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | namespace: gloo-system 4 | metadata: 5 | name: gloo-system 6 | commonLabels: 7 | app: gloo-system 8 | resources: 9 | - namespace.yaml 10 | - helmRepository.yaml 11 | - helmRelease.yaml 12 | - gateway.yaml 13 | - upstreams.yaml 14 | - virtualServices.yaml 15 | - settings.yaml -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/virtualServices.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: gateway.solo.io/v1 2 | kind: VirtualService 3 | metadata: 4 | name: default 5 | namespace: gloo-system 6 | spec: 7 | virtualHost: 8 | domains: 9 | - '*' 10 | routes: 11 | - matchers: 12 | - prefix: / 13 | directResponseAction: 14 | status: 404 15 | body: 'whoops, service is not found' 16 | --- -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/report/repository.go: -------------------------------------------------------------------------------- 1 | package report 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/syafdia/demo-es/internal/domain" 7 | ) 8 | 9 | type ReportRepository interface { 10 | Store(ctx context.Context, taskReport TaskReport) error 11 | Update(ctx context.Context, taskReport TaskReport) error 12 | FindByTaskID(ctx context.Context, taskID domain.ID) (TaskReport, error) 13 | } 14 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/di/app_module.go: -------------------------------------------------------------------------------- 1 | package di 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type AppModule struct { 8 | } 9 | 10 | func NewAppModule() *AppModule { 11 | return &AppModule{} 12 | } 13 | 14 | var onceAppModule sync.Once 15 | var appModule *AppModule 16 | 17 | func GetAppModule() *AppModule { 18 | onceAppModule.Do(func() { 19 | appModule = NewAppModule() 20 | }) 21 | 22 | return appModule 23 | } 24 | -------------------------------------------------------------------------------- /src/etc/demo-nats/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-nats 2 | 3 | go 1.20 4 | 5 | require github.com/nats-io/nats.go v1.36.0 6 | 7 | require ( 8 | github.com/klauspost/compress v1.17.2 // indirect 9 | github.com/nats-io/nkeys v0.4.7 // indirect 10 | github.com/nats-io/nuid v1.0.1 // indirect 11 | golang.org/x/crypto v0.18.0 // indirect 12 | golang.org/x/sys v0.16.0 // indirect 13 | golang.org/x/text v0.14.0 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /src/etc/go-calculator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build binary. 2 | FROM golang:1.20 AS builder 3 | 4 | WORKDIR /app 5 | 6 | COPY go.mod go.sum ./ 7 | RUN go mod download 8 | 9 | COPY *.go ./ 10 | 11 | RUN CGO_ENABLED=0 GOOS=linux go build -o /go-calculator 12 | 13 | # Pack binary. 14 | FROM ubuntu:22.04 AS build-release-stage 15 | 16 | WORKDIR /home 17 | 18 | COPY --from=builder /go-calculator ./go-calculator 19 | 20 | EXPOSE 8080 21 | 22 | CMD ["./go-calculator"] -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/redis-cache/values.yaml: -------------------------------------------------------------------------------- 1 | nameOverride: "redis-cache" 2 | fullnameOverride: "redis-cache" 3 | architecture: standalone 4 | replica: 5 | replicaCount: 0 6 | auth: 7 | enabled: false 8 | password: "rediscachepassword" 9 | master: 10 | disableCommands: [] 11 | persistence: 12 | enabled: false 13 | resources: 14 | limits: 15 | cpu: 500m 16 | memory: 256Mi 17 | requests: 18 | cpu: 300m 19 | memory: 128Mi -------------------------------------------------------------------------------- /src/concurrency/semaphore/semaphore.go: -------------------------------------------------------------------------------- 1 | package semaphore 2 | 3 | type Semaphore interface { 4 | Acquire() 5 | Release() 6 | } 7 | 8 | type semaphore struct { 9 | semC chan struct{} 10 | } 11 | 12 | func New(maxConcurrency int) Semaphore { 13 | return &semaphore{ 14 | semC: make(chan struct{}, maxConcurrency), 15 | } 16 | } 17 | 18 | func (s *semaphore) Acquire() { 19 | s.semC <- struct{}{} 20 | } 21 | 22 | func (s *semaphore) Release() { 23 | <-s.semC 24 | } 25 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/infrastructure/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/syafdia/demo-es/internal/domain/communication" 8 | ) 9 | 10 | type EmailService struct{} 11 | 12 | func NewEmailService() *EmailService { 13 | return &EmailService{} 14 | } 15 | 16 | func (e *EmailService) SendEmail(ctx context.Context, message communication.EmailMessage) { 17 | fmt.Println("Send email:", message) 18 | } 19 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/auth/clients.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "context" 5 | ) 6 | 7 | type Client struct { 8 | HydraAdmin *HydraAdmin 9 | } 10 | 11 | func NewClient() *Client { 12 | return &Client{} 13 | } 14 | 15 | type HydraAdmin struct { 16 | } 17 | 18 | type AcceptLoginChallengeRequest struct { 19 | LoginChallenge string 20 | } 21 | 22 | func (h *HydraAdmin) AcceptLoginChallenge(ctx context.Context, in AcceptLoginChallengeRequest) error { 23 | return nil 24 | } 25 | -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/delivery/utils.go: -------------------------------------------------------------------------------- 1 | package delivery 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | 8 | "github.com/syafdia/xaam/internal/domain/entity" 9 | ) 10 | 11 | func handleError(ctx *gin.Context, err error) { 12 | if errr, ok := err.(*entity.Err); ok { 13 | ctx.JSON(errr.Status, gin.H{ 14 | "message": errr.Error(), 15 | }) 16 | return 17 | } 18 | 19 | ctx.JSON(http.StatusInternalServerError, gin.H{ 20 | "message": err.Error(), 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/helmRelease.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 2 | kind: HelmRelease 3 | metadata: 4 | name: gloo-system 5 | namespace: gloo-system 6 | spec: 7 | interval: 5m 8 | chart: 9 | spec: 10 | chart: gloo 11 | version: 1.17.15 12 | sourceRef: 13 | kind: HelmRepository 14 | name: solo-helm-repository 15 | namespace: gloo-system 16 | values: 17 | discovery: 18 | enabled: false 19 | 20 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/repo/resource_repo.go: -------------------------------------------------------------------------------- 1 | package repo 2 | 3 | import ( 4 | "context" 5 | 6 | e "github.com/syafdia/xaam/internal/domain/entity" 7 | ) 8 | 9 | // mockgen -source=internal/domain/repo/resource_repo.go -destination=internal/mock/domain/repo/resource_repo.go 10 | type ResourceRepo interface { 11 | FindMultipleByIDs(ctx context.Context, ids []int64) (map[int64]e.Resource, error) 12 | FindMultipleByNames(ctx context.Context, names []string) (map[string]e.Resource, error) 13 | } 14 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/virtualService.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: gateway.solo.io/v1 2 | kind: VirtualService 3 | metadata: 4 | name: calculator-vs 5 | namespace: calculator 6 | spec: 7 | virtualHost: 8 | domains: 9 | - calculator.service.local 10 | options: 11 | extauth: 12 | customAuth: {} 13 | routes: 14 | - matchers: 15 | - prefix: / 16 | delegateAction: 17 | ref: 18 | name: calculator-deployment 19 | namespace: calculator -------------------------------------------------------------------------------- /src/etc/XAAM/e2e/ping_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "net/http" 5 | "reflect" 6 | "testing" 7 | 8 | "github.com/dghubble/sling" 9 | ) 10 | 11 | func Test_GetPing_200(t *testing.T) { 12 | client := &http.Client{} 13 | req, _ := sling.New().Get("http://0.0.0.0:8080/ping").Request() 14 | 15 | resp, _ := client.Do(req) 16 | defer resp.Body.Close() 17 | 18 | if !reflect.DeepEqual(resp.StatusCode, http.StatusOK) { 19 | t.Errorf("http status is not 200, got %d", resp.StatusCode) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/internal/domain/error.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import "github.com/syafdia/clean-arch-ddd-cqrs-es/pkg/errr" 4 | 5 | type ErrorCode string 6 | 7 | type ValidationError struct { 8 | errr.Err 9 | } 10 | 11 | func NewValidationError(code ErrorCode, message string) *ValidationError { 12 | return &ValidationError{*errr.NewErr(string(code), message)} 13 | } 14 | 15 | var ( 16 | ErrNotImplemented = errr.NewErr("CORE-FEATURE_NOT_IMPLEMENTED", "feature is not implemented yet") 17 | ) 18 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/example/e01/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/syafdia/go-exercise/src/concurrency/pipeline/example" 8 | ) 9 | 10 | func main() { 11 | startTime := time.Now() 12 | 13 | for i := 0; i < 3; i++ { 14 | val := example.AddFoo(example.AddQuoute(example.Square(example.MultiplyTwo(i)))) 15 | fmt.Printf("Input: %d, Output %s\n", i, val) 16 | 17 | } 18 | 19 | fmt.Printf("Elapsed time without concurrency: %s\n", time.Since(startTime)) 20 | } 21 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/postgresql-core/helmRelease.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 2 | kind: HelmRelease 3 | metadata: 4 | name: postgresql-core 5 | spec: 6 | interval: 5m 7 | chart: 8 | spec: 9 | chart: postgresql 10 | version: 12.5.6 11 | sourceRef: 12 | kind: HelmRepository 13 | name: bitnami-helm-repository 14 | values: 15 | auth: 16 | username: "postgresqlcore" 17 | password: "postgresqlcorepassword" 18 | database: "postgresqlcore" 19 | -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/postgresql-core/helmRelease.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 2 | kind: HelmRelease 3 | metadata: 4 | name: postgresql-core 5 | spec: 6 | interval: 5m 7 | chart: 8 | spec: 9 | chart: postgresql 10 | version: 12.5.6 11 | sourceRef: 12 | kind: HelmRepository 13 | name: bitnami-helm-repository 14 | values: 15 | auth: 16 | username: "postgresqlcore" 17 | password: "postgresqlcorepassword" 18 | database: "postgresqlcore" 19 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/example/util.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func MultiplyTwo(v int) int { 9 | time.Sleep(2 * time.Second) 10 | return v * 2 11 | } 12 | 13 | func Square(v int) int { 14 | time.Sleep(2 * time.Second) 15 | return v * v 16 | } 17 | 18 | func AddQuoute(v int) string { 19 | time.Sleep(2 * time.Second) 20 | return fmt.Sprintf("'%d'", v) 21 | } 22 | 23 | func AddFoo(v string) string { 24 | time.Sleep(2 * time.Second) 25 | return fmt.Sprintf("Foo %v", v) 26 | } 27 | -------------------------------------------------------------------------------- /src/etc/XAAM/cmd/http/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/syafdia/xaam/internal/delivery" 6 | "github.com/syafdia/xaam/internal/di" 7 | ) 8 | 9 | func main() { 10 | appModule := di.GetAppModule() 11 | repoModule := di.GetRepoModule(appModule) 12 | useCaseModule := di.GetUseCaseModule(repoModule) 13 | 14 | r := gin.Default() 15 | r.GET("/ping", delivery.GetPingHandler()) 16 | r.POST("/api/v1/authorisation/check", delivery.PostAuthorisationHandler(useCaseModule)) 17 | 18 | r.Run() 19 | } 20 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/redis-cache/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: redis-deployment 5 | namespace: redis-cache 6 | labels: 7 | type: db 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | appName: redis-cache 13 | progressDeadlineSeconds: 60 14 | template: 15 | metadata: 16 | labels: 17 | appName: redis-cache 18 | spec: 19 | containers: 20 | - name: redis-cache 21 | image: redis:7.0 22 | ports: 23 | - containerPort: 6379 -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/overlays/production/redis-cache/values.yaml: -------------------------------------------------------------------------------- 1 | nameOverride: "redis-cache" 2 | fullnameOverride: "redis-cache" 3 | architecture: standalone 4 | replica: 5 | replicaCount: 0 6 | image: 7 | registry: docker.io 8 | repository: bitnami/redis 9 | tag: 6.2.3-debian-10-r0 10 | auth: 11 | enabled: true 12 | password: "rediscachepassword" 13 | master: 14 | disableCommands: [] 15 | persistence: 16 | enabled: false 17 | resources: 18 | limits: 19 | cpu: 750m 20 | memory: 256Mi 21 | requests: 22 | cpu: 500m 23 | memory: 128Mi -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go Exercise 2 | 3 | Exercise for learning Go programming language, includes : 4 | 5 | ## Data structure 6 | * Binary Tree 7 | * Hashmap 8 | * [Linked List](src/datastructure/linkedlist) 9 | * [Queue](src/datastructure/queue) 10 | * Stack 11 | 12 | 13 | ## Concurrency 14 | * [Pipeline](src/concurrency/pipeline) 15 | * [Semaphore](src/concurrency/semaphore) 16 | * [Worker Pool](src/concurrency/workerpool) 17 | 18 | ## Etc 19 | * [Kong Plugin](src/etc/demo-kong-plugin) 20 | * [Redlock](src/etc/demo-redlock) 21 | * [Unit Test](src/etc/demo-unit-test) 22 | 23 | ## Network 24 | * TBA -------------------------------------------------------------------------------- /src/etc/kafka/basic/publisher/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | kafka "github.com/segmentio/kafka-go" 8 | ) 9 | 10 | func main() { 11 | w := &kafka.Writer{ 12 | Addr: kafka.TCP("localhost:9092"), 13 | Topic: "topic-1", 14 | Balancer: &kafka.LeastBytes{}, 15 | } 16 | 17 | defer w.Close() 18 | 19 | err := w.WriteMessages(context.Background(), kafka.Message{ 20 | Key: []byte("Key-A"), 21 | Value: []byte("Hello World!"), 22 | }) 23 | 24 | if err != nil { 25 | log.Fatal("failed when writing message, err:", err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/etc/clean-arch-ddd-cqrs-es/internal/domain/task/error_code.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import "github.com/syafdia/clean-arch-ddd-cqrs-es/internal/domain" 4 | 5 | const ( 6 | ErrCodeInvalidTitleLength domain.ErrorCode = "TASK-INVALID_TITLE_LENGTH" 7 | ErrCodeInvalidDescriptionLength domain.ErrorCode = "TASK-INVALID_DESCRIPTION" 8 | ErrCodeInvalidStateTransition domain.ErrorCode = "TASK-INVALID_STATE_TRANSITION" 9 | ErrCodeInvalidTagNameLength domain.ErrorCode = "TASK-INVALID_TAG_NAME_LENGTH" 10 | ErrCodeTagAlreadyExists domain.ErrorCode = "TASK-TAG_ALREADY_EXISTS" 11 | ) 12 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/auth/check_request.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | type CheckResourceRequest struct { 4 | Kind string `json:"kind"` 5 | } 6 | 7 | type CheckPrincipalRequest struct { 8 | Kind string `json:"kind"` 9 | ID string `json:"id"` 10 | Roles []string `json:"roles"` 11 | Metadata map[string]string `json:"metadata"` 12 | } 13 | 14 | type CheckRequest struct { 15 | Actions []string `json:"actions"` 16 | Resource CheckResourceRequest `json:"resource"` 17 | Principal CheckPrincipalRequest `json:"principal"` 18 | } 19 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/data/token_repository.go: -------------------------------------------------------------------------------- 1 | package data 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/syafdia/demo-kong-plugin/internal/domain/repo" 8 | ) 9 | 10 | type tokenRepository struct { 11 | } 12 | 13 | func NewTokenRepository() repo.TokenRepository { 14 | return &tokenRepository{} 15 | } 16 | 17 | func (t *tokenRepository) ExchangeToken(ctx context.Context, key string) (string, error) { 18 | return fmt.Sprintf("%s-thisisasecrettoken", key), nil 19 | } 20 | 21 | func (t *tokenRepository) Invalidate(ctx context.Context, token string) error { 22 | return nil 23 | } 24 | -------------------------------------------------------------------------------- /src/etc/kafka/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | zookeeper: 4 | image: 'bitnami/zookeeper:latest' 5 | ports: 6 | - '2181:2181' 7 | environment: 8 | - ALLOW_ANONYMOUS_LOGIN=yes 9 | kafka: 10 | image: 'bitnami/kafka:latest' 11 | ports: 12 | - '9092:9092' 13 | environment: 14 | - KAFKA_BROKER_ID=1 15 | - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092 16 | - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://127.0.0.1:9092 17 | - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181 18 | - ALLOW_PLAINTEXT_LISTENER=yes 19 | depends_on: 20 | - zookeeper -------------------------------------------------------------------------------- /src/etc/kafka/basic/consumer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/segmentio/kafka-go" 8 | ) 9 | 10 | func main() { 11 | r := kafka.NewReader(kafka.ReaderConfig{ 12 | Brokers: []string{"localhost:9092"}, 13 | Topic: "topic-1", 14 | Partition: 0, 15 | MinBytes: 10e3, // 10KB 16 | MaxBytes: 10e6, // 10MB 17 | }) 18 | 19 | defer r.Close() 20 | 21 | for { 22 | m, err := r.ReadMessage(context.Background()) 23 | if err != nil { 24 | break 25 | } 26 | fmt.Printf("message at offset %d: %s = %s\n", m.Offset, string(m.Key), string(m.Value)) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Develop Kong plugin using Go 2 | 3 | ### How to Develop 4 | 5 | 1. Install [Docker](https://www.docker.com) 6 | 7 | 2. Install [CompileDaemon](https://github.com/githubnemo/CompileDaemon) 8 | ``` 9 | go get github.com/githubnemo/CompileDaemon 10 | 11 | ``` 12 | 13 | 2. Run development script 14 | ``` 15 | sh scripts/start-development.sh 16 | ``` 17 | 18 | 19 | ### How to test 20 | 1. Visit `curl --location --request GET '0.0.0.0:8000?key=invalidconsumerkey'`, it will return `401` 21 | 2. Visit `curl --location --request GET '0.0.0.0:8000?key=mysecretconsumerkey'`, it will return `200` with valid data -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/development/apps.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.toolkit.fluxcd.io/v1 2 | kind: Kustomization 3 | metadata: 4 | name: calculator 5 | namespace: flux-system 6 | spec: 7 | interval: 1m0s 8 | sourceRef: 9 | kind: GitRepository 10 | name: flux-system 11 | path: ./src/k8s/demo-flux/apps/base/calculator 12 | prune: true 13 | --- 14 | apiVersion: kustomize.toolkit.fluxcd.io/v1 15 | kind: Kustomization 16 | metadata: 17 | name: redis-cache 18 | namespace: flux-system 19 | spec: 20 | interval: 1m0s 21 | sourceRef: 22 | kind: GitRepository 23 | name: flux-system 24 | path: ./src/k8s/demo-flux/apps/base/redis-cache 25 | prune: true 26 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/di/repo_module.go: -------------------------------------------------------------------------------- 1 | package di 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/syafdia/demo-kong-plugin/internal/data" 7 | "github.com/syafdia/demo-kong-plugin/internal/domain/repo" 8 | ) 9 | 10 | type RepoModule struct { 11 | TokenRepository repo.TokenRepository 12 | } 13 | 14 | func NewRepoModule(appModule *AppModule) *RepoModule { 15 | return &RepoModule{ 16 | TokenRepository: data.NewTokenRepository(), 17 | } 18 | } 19 | 20 | var onceRepoModule sync.Once 21 | var repoModule *RepoModule 22 | 23 | func GetRepoModule() *RepoModule { 24 | onceRepoModule.Do(func() { 25 | repoModule = NewRepoModule(GetAppModule()) 26 | }) 27 | 28 | return repoModule 29 | } 30 | -------------------------------------------------------------------------------- /src/concurrency/semaphore/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/syafdia/go-exercise/src/concurrency/semaphore" 8 | ) 9 | 10 | func main() { 11 | sem := semaphore.New(3) 12 | doneC := make(chan bool, 1) 13 | totProcess := 10 14 | 15 | for i := 1; i <= totProcess; i++ { 16 | sem.Acquire() 17 | go func(v int) { 18 | defer sem.Release() 19 | longRunningProcess(v) 20 | 21 | if v == totProcess { 22 | doneC <- true 23 | } 24 | }(i) 25 | } 26 | 27 | <-doneC 28 | } 29 | 30 | func longRunningProcess(taskID int) { 31 | fmt.Println(time.Now().Format("15:04:05"), "Running task with ID", taskID) 32 | time.Sleep(2 * time.Second) 33 | } 34 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/entity/errors.go: -------------------------------------------------------------------------------- 1 | package entity 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | ) 7 | 8 | type Err struct { 9 | Errr error 10 | Status int 11 | } 12 | 13 | func NewErr(status int, message string) error { 14 | return &Err{Status: status, Errr: errors.New(message)} 15 | } 16 | 17 | func WrapErr(status int, err error) error { 18 | return &Err{Status: status, Errr: err} 19 | } 20 | 21 | func (e *Err) Error() string { 22 | return e.Errr.Error() 23 | } 24 | 25 | func (e *Err) Unwrap() error { 26 | return e.Errr 27 | } 28 | 29 | var ( 30 | ErrNotFound = NewErr(http.StatusNotFound, "not found") 31 | ErrBadRequest = NewErr(http.StatusBadRequest, "bad request") 32 | ) 33 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/canary.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: flagger.app/v1beta1 2 | kind: Canary 3 | metadata: 4 | name: calculator-canary 5 | namespace: calculator 6 | spec: 7 | provider: gloo 8 | targetRef: 9 | apiVersion: apps/v1 10 | kind: Deployment 11 | name: calculator-deployment 12 | service: 13 | port: 8080 14 | targetPort: 8080 15 | analysis: 16 | # schedule interval (default 60s) 17 | interval: 10s 18 | # max number of failed metric checks before rollback 19 | threshold: 5 20 | # max traffic percentage routed to canary 21 | # percentage (0-100) 22 | maxWeight: 50 23 | # canary increment step 24 | # percentage (0-100) 25 | stepWeight: 10 -------------------------------------------------------------------------------- /src/k8s/demo-kustomization/base/calculator/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: calculator-deployment 5 | labels: 6 | app: calculator 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: calculator 12 | template: 13 | metadata: 14 | labels: 15 | app: calculator 16 | spec: 17 | containers: 18 | - name: go-calculator 19 | image: syafdia/go-calculator:latest 20 | ports: 21 | - containerPort: 8080 22 | env: 23 | - name: MAX_NUMBER 24 | valueFrom: 25 | configMapKeyRef: 26 | name: calculator-configmap 27 | key: max_number -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/pokedex/handlers.go: -------------------------------------------------------------------------------- 1 | package pokedex 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/gin-gonic/gin" 9 | ) 10 | 11 | type PokedexHandler struct { 12 | client *Client 13 | } 14 | 15 | func NewPokedexhandler(client *Client) *PokedexHandler { 16 | return &PokedexHandler{ 17 | client: client, 18 | } 19 | } 20 | 21 | func (a *PokedexHandler) ListPokemons(c *gin.Context) { 22 | authCodeURL := a.client.OAuth2.AuthCodeURL(fmt.Sprintf("%d", time.Now().Unix())) 23 | c.HTML(http.StatusOK, "pokemons.list", map[string]interface{}{ 24 | "AuthCodeURL": authCodeURL, 25 | }) 26 | } 27 | 28 | func (a *PokedexHandler) OAuth2Callbacks(c *gin.Context) { 29 | // TODO 30 | } 31 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/user/usecase.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import "context" 4 | 5 | type RegisterUserUseCase interface { 6 | Execute(ctx context.Context, input CreateUserInput) (User, error) 7 | } 8 | 9 | type registerUserUseCase struct { 10 | userRepo UserRepo 11 | } 12 | 13 | func NewRegisterUserUseCase( 14 | userRepo UserRepo, 15 | ) RegisterUserUseCase { 16 | return ®isterUserUseCase{userRepo: userRepo} 17 | } 18 | 19 | func (w *registerUserUseCase) Execute(ctx context.Context, input CreateUserInput) (User, error) { 20 | user, err := w.userRepo.Create(ctx, input) 21 | if err != nil { 22 | return User{}, err 23 | } 24 | 25 | // Do something 26 | // ... 27 | // ... 28 | 29 | return user, nil 30 | } 31 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/staging/flux-system/gotk-sync.yaml: -------------------------------------------------------------------------------- 1 | # This manifest was generated by flux. DO NOT EDIT. 2 | --- 3 | apiVersion: source.toolkit.fluxcd.io/v1 4 | kind: GitRepository 5 | metadata: 6 | name: flux-system 7 | namespace: flux-system 8 | spec: 9 | interval: 1m0s 10 | ref: 11 | branch: master 12 | secretRef: 13 | name: flux-system 14 | url: ssh://git@github.com/syafdia/go-exercise 15 | --- 16 | apiVersion: kustomize.toolkit.fluxcd.io/v1 17 | kind: Kustomization 18 | metadata: 19 | name: flux-system 20 | namespace: flux-system 21 | spec: 22 | interval: 10m0s 23 | path: ./src/k8s/demo-flux/clusters/staging 24 | prune: true 25 | sourceRef: 26 | kind: GitRepository 27 | name: flux-system 28 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/development/flux-system/gotk-sync.yaml: -------------------------------------------------------------------------------- 1 | # This manifest was generated by flux. DO NOT EDIT. 2 | --- 3 | apiVersion: source.toolkit.fluxcd.io/v1 4 | kind: GitRepository 5 | metadata: 6 | name: flux-system 7 | namespace: flux-system 8 | spec: 9 | interval: 1m0s 10 | ref: 11 | branch: master 12 | secretRef: 13 | name: flux-system 14 | url: ssh://git@github.com/syafdia/go-exercise 15 | --- 16 | apiVersion: kustomize.toolkit.fluxcd.io/v1 17 | kind: Kustomization 18 | metadata: 19 | name: flux-system 20 | namespace: flux-system 21 | spec: 22 | interval: 10m0s 23 | path: ./src/k8s/demo-flux/clusters/development 24 | prune: true 25 | sourceRef: 26 | kind: GitRepository 27 | name: flux-system 28 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/domain/usecase/keychecker/get_token_use_case.go: -------------------------------------------------------------------------------- 1 | package keychecker 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "github.com/syafdia/demo-kong-plugin/internal/domain/repo" 8 | ) 9 | 10 | type GetTokenUseCase interface { 11 | Execute(ctx context.Context, key string) (string, error) 12 | } 13 | 14 | type getTokenUseCase struct { 15 | tokenRepo repo.TokenRepository 16 | } 17 | 18 | func NewGetTokenUseCase(tokenRepo repo.TokenRepository) GetTokenUseCase { 19 | return &getTokenUseCase{tokenRepo} 20 | } 21 | 22 | func (v *getTokenUseCase) Execute(ctx context.Context, key string) (string, error) { 23 | log.Println("[GetTokenUseCase] Start get token use case") 24 | return v.tokenRepo.ExchangeToken(ctx, key) 25 | } 26 | -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ .Release.Name }}-deployment 5 | labels: 6 | app: {{ .Release.Name }} 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: {{ .Release.Name }} 12 | template: 13 | metadata: 14 | labels: 15 | app: {{ .Release.Name }} 16 | spec: 17 | containers: 18 | - name: go-calculator 19 | image: syafdia/go-calculator:latest 20 | ports: 21 | - containerPort: 8080 22 | env: 23 | - name: MAX_NUMBER 24 | valueFrom: 25 | configMapKeyRef: 26 | name: {{ .Release.Name }}-configmap 27 | key: max_number -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/user/entity.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | type Gender string 4 | 5 | const ( 6 | GenderMale Gender = "male" 7 | GenderFemale Gender = "female" 8 | GenderOther Gender = "other" 9 | ) 10 | 11 | type User struct { 12 | ID int64 `json:"id"` 13 | Email string `json:"email"` 14 | FirstName string `json:"first_name"` 15 | LastName string `json:"last_name"` 16 | Gender Gender `json:"gender"` 17 | } 18 | 19 | type CreateUserInput struct { 20 | Email string `json:"email"` 21 | FirstName string `json:"first_name"` 22 | LastName string `json:"last_name"` 23 | Gender Gender `json:"gender"` 24 | } 25 | 26 | type UpdateUserInput struct { 27 | FirstName string 28 | LastName string 29 | Gender Gender 30 | } 31 | -------------------------------------------------------------------------------- /src/distributed/semaphore/go.sum: -------------------------------------------------------------------------------- 1 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 2 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 3 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 4 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 5 | github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= 6 | github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= 7 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 8 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 9 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/flagger/helmRelease.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 2 | kind: HelmRelease 3 | metadata: 4 | name: flagger-helm-release 5 | namespace: flagger 6 | spec: 7 | install: 8 | remediation: 9 | retries: 5 10 | remediateLastFailure: True 11 | upgrade: 12 | remediation: 13 | retries: 5 14 | remediateLastFailure: True 15 | timeout: 15m 16 | targetNamespace: flagger 17 | interval: 5m 18 | chart: 19 | spec: 20 | chart: flagger 21 | version: 1.34.0 22 | sourceRef: 23 | kind: HelmRepository 24 | name: flagger-helm-repository 25 | namespace: flagger 26 | values: 27 | crds: 28 | create: true 29 | fullnameOverride: flagger 30 | meshProvider: gloo 31 | includeLabelPrefix: '*' -------------------------------------------------------------------------------- /src/etc/demo-unit-test/usecase_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/syafdia/demo-unit-test/internal/user" 8 | ) 9 | 10 | func TestNewRegisterUserUseCase(t *testing.T) { 11 | type args struct { 12 | userRepo user.UserRepo 13 | } 14 | tests := []struct { 15 | name string 16 | args args 17 | want user.RegisterUserUseCase 18 | }{ 19 | { 20 | name: "success creating RegisterUserUseCase instance", 21 | args: args{}, 22 | want: user.NewRegisterUserUseCase(nil), 23 | }, 24 | } 25 | for _, tt := range tests { 26 | t.Run(tt.name, func(t *testing.T) { 27 | if got := user.NewRegisterUserUseCase(tt.args.userRepo); !reflect.DeepEqual(got, tt.want) { 28 | t.Errorf("NewRegisterUserUseCase() = %v, want %v", got, tt.want) 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/domain/usecase/business/find_one_by_business_id_use_case.go: -------------------------------------------------------------------------------- 1 | package business 2 | 3 | import ( 4 | "context" 5 | 6 | be "github.com/syafdia/xaam/internal/domain/entity/business" 7 | "github.com/syafdia/xaam/internal/domain/repo" 8 | ) 9 | 10 | type FindOneByBusinessIDUseCase interface { 11 | Execute(ctx context.Context, businessID string) (be.GetOneResponse, error) 12 | } 13 | 14 | type findOneByBusinessIDUC struct { 15 | businessRepo repo.BusinessRepo 16 | } 17 | 18 | func NewFindOneByBusinessIDUseCase(businessRepo repo.BusinessRepo) FindOneByBusinessIDUseCase { 19 | return &findOneByBusinessIDUC{businessRepo: businessRepo} 20 | } 21 | 22 | func (g *findOneByBusinessIDUC) Execute(ctx context.Context, businessID string) (be.GetOneResponse, error) { 23 | return g.businessRepo.FindOneByBusinessID(ctx, businessID) 24 | } 25 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/apps/base/calculator/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: calculator-deployment 5 | namespace: calculator 6 | labels: 7 | app: calculator 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | appName: calculator 13 | template: 14 | metadata: 15 | labels: 16 | appName: calculator 17 | spec: 18 | containers: 19 | - name: go-calculator 20 | image: syafdia/go-calculator:latest 21 | ports: 22 | - containerPort: 8080 23 | env: 24 | - name: MAX_NUMBER 25 | valueFrom: 26 | configMapKeyRef: 27 | name: calculator-configmap 28 | key: max_number 29 | - name: REDIS_URL 30 | value: 'redis://redis-service.redis-cache.svc.cluster.local:6379' -------------------------------------------------------------------------------- /src/datastructure/queue/queue.go: -------------------------------------------------------------------------------- 1 | package queue 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/syafdia/go-exercise/src/datastructure/types" 7 | ) 8 | 9 | type Queue interface { 10 | Enqueue(v types.T) 11 | Dequeue() types.T 12 | Size() int 13 | String() string 14 | } 15 | 16 | type queue struct { 17 | values []types.T 18 | } 19 | 20 | func New() Queue { 21 | return &queue{ 22 | values: []types.T{}, 23 | } 24 | } 25 | 26 | func (q *queue) Enqueue(v types.T) { 27 | q.values = append(q.values, v) 28 | } 29 | 30 | func (q *queue) Dequeue() types.T { 31 | if q.Size() == 0 { 32 | return nil 33 | } 34 | 35 | v := q.values[0] 36 | q.values = q.values[1:] 37 | 38 | return v 39 | } 40 | 41 | func (q *queue) Size() int { 42 | return len(q.values) 43 | } 44 | 45 | func (q *queue) String() string { 46 | return fmt.Sprintf("%v", q.values) 47 | } 48 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/gloo-system/settings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: gloo.solo.io/v1 2 | kind: Settings 3 | metadata: 4 | name: default 5 | namespace: gloo-system 6 | spec: 7 | discoveryNamespace: gloo-system 8 | gateway: 9 | validation: 10 | alwaysAccept: true 11 | proxyValidationServerAddr: gloo:9988 12 | gloo: 13 | xdsBindAddr: 0.0.0.0:9977 14 | kubernetesArtifactSource: {} 15 | kubernetesConfigSource: {} 16 | kubernetesSecretSource: {} 17 | refreshRate: 60s 18 | extauth: 19 | extauthzServerRef: 20 | name: auth-server-upstream 21 | namespace: gloo-system 22 | httpService: 23 | request: 24 | allowedHeadersRegex: ['.*'] 25 | response: 26 | allowedUpstreamHeaders: 27 | - 'x-user-context' 28 | requestBody: 29 | maxRequestBytes: 10240 30 | requestTimeout: 0.5s -------------------------------------------------------------------------------- /src/concurrency/pipeline/example/e02/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/syafdia/go-exercise/src/concurrency/pipeline/example" 9 | ) 10 | 11 | func main() { 12 | N := 3 // Foo '0',Foo '4',Foo '16' -> Sequence is not guarantee. 13 | startTime := time.Now() 14 | valC := make(chan string, N) 15 | 16 | fmt.Printf("Input: %d\n", N) 17 | 18 | for i := 0; i < N; i++ { 19 | go func(input int) { 20 | val := example.AddFoo(example.AddQuoute(example.Square(example.MultiplyTwo(input)))) 21 | 22 | valC <- val 23 | }(i) 24 | } 25 | 26 | vals := []string{} 27 | for i := 0; i < N; i++ { 28 | vals = append(vals, <-valC) 29 | } 30 | 31 | result := strings.Join(vals, ",") 32 | 33 | fmt.Printf("Result: %s\n", result) 34 | fmt.Printf("Elapsed time without concurrency: %s", time.Since(startTime)) 35 | } 36 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/di/usecase_module.go: -------------------------------------------------------------------------------- 1 | package di 2 | 3 | import ( 4 | "sync" 5 | 6 | keycheckerusecase "github.com/syafdia/demo-kong-plugin/internal/domain/usecase/keychecker" 7 | ) 8 | 9 | type UseCaseModule struct { 10 | ValidateKeyUseCase keycheckerusecase.ValidateKeyUseCase 11 | GetTokenUseCase keycheckerusecase.GetTokenUseCase 12 | } 13 | 14 | func NewUseCaseModule(repoModule *RepoModule) *UseCaseModule { 15 | return &UseCaseModule{ 16 | ValidateKeyUseCase: keycheckerusecase.NewValidateKeyUseCase(), 17 | GetTokenUseCase: keycheckerusecase.NewGetTokenUseCase(repoModule.TokenRepository), 18 | } 19 | } 20 | 21 | var onceUseCaseModule sync.Once 22 | var useCaseModule *UseCaseModule 23 | 24 | func GetUseCaseModule() *UseCaseModule { 25 | onceUseCaseModule.Do(func() { 26 | useCaseModule = NewUseCaseModule(GetRepoModule()) 27 | }) 28 | 29 | return useCaseModule 30 | } 31 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/datadog/helmRelease.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: helm.toolkit.fluxcd.io/v2beta1 2 | kind: HelmRelease 3 | metadata: 4 | name: datadog 5 | namespace: datadog 6 | spec: 7 | interval: 5m 8 | chart: 9 | spec: 10 | chart: datadog 11 | version: 3.32.7 12 | sourceRef: 13 | kind: HelmRepository 14 | name: datadog-helm-repository 15 | namespace: flux-system 16 | values: 17 | targetSystem: linux 18 | datadog: 19 | apiKey: xxxx 20 | site: xxxx 21 | logs: 22 | enabled: true 23 | containerCollectAll: true 24 | confd: 25 | openmetrics.yaml: | 26 | init_config: 27 | instances: 28 | - prometheus_url: https://foo-bar/metrics 29 | namespace: foo_bar 30 | ssl_ca_cert: false 31 | metrics: 32 | - foo 33 | 34 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/auth/repositories.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "context" 4 | 5 | type Repo struct { 6 | User *UserRepo 7 | } 8 | 9 | func NewRepo() *Repo { 10 | return &Repo{ 11 | User: NewUserRepo(), 12 | } 13 | } 14 | 15 | type UserRepo struct { 16 | stores []User 17 | } 18 | 19 | func NewUserRepo() *UserRepo { 20 | u := &UserRepo{} 21 | u.seed() 22 | 23 | return u 24 | } 25 | 26 | func (u *UserRepo) FindByUsernameAndPassword(_ctx context.Context, username string, password string) (User, error) { 27 | for _, user := range u.stores { 28 | if user.Username == username && user.Password == password { 29 | return user, nil 30 | } 31 | } 32 | 33 | return User{}, ErrNotFound 34 | } 35 | 36 | func (u *UserRepo) seed() { 37 | u.stores = []User{ 38 | {ID: "usr-0001", Username: "john123", Password: "123"}, 39 | {ID: "usr-0002", Username: "doe456", Password: "456"}, 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/pkg/calc/calc_test.go: -------------------------------------------------------------------------------- 1 | package calc 2 | 3 | import "testing" 4 | 5 | func TestFactorial(t *testing.T) { 6 | type args struct { 7 | n uint 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want uint 13 | }{ 14 | { 15 | name: "N is 5", 16 | args: args{n: 5}, 17 | want: 120, 18 | }, 19 | { 20 | name: "N is 0", 21 | args: args{n: 0}, 22 | want: 1, 23 | }, 24 | { 25 | name: "N is 1", 26 | args: args{n: 1}, 27 | want: 1, 28 | }, 29 | { 30 | name: "N is 3", 31 | args: args{n: 3}, 32 | want: 6, 33 | }, 34 | { 35 | name: "N is 10", 36 | args: args{n: 10}, 37 | want: 3628800, 38 | }, 39 | } 40 | for _, tt := range tests { 41 | t.Run(tt.name, func(t *testing.T) { 42 | if got := Factorial(tt.args.n); got != tt.want { 43 | t.Errorf("Factorial() = %v, want %v", got, tt.want) 44 | } 45 | }) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/report/report.go: -------------------------------------------------------------------------------- 1 | package report 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/syafdia/demo-es/internal/domain" 7 | "github.com/syafdia/demo-es/internal/domain/task" 8 | ) 9 | 10 | type TaskReport struct { 11 | ID domain.ID 12 | TaskID domain.ID 13 | TaskTitle string 14 | StartedAt time.Time 15 | FinishedAt time.Time 16 | Duration time.Duration 17 | } 18 | 19 | func NewTaskReport() TaskReport { 20 | return TaskReport{ 21 | ID: domain.NewID(), 22 | } 23 | } 24 | 25 | func (t *TaskReport) ApplyEvent(event domain.Event) { 26 | switch e := event.(type) { 27 | case task.TaskCreated: 28 | t.TaskID = e.ID 29 | t.TaskTitle = e.Title 30 | t.StartedAt = e.OccuredAt() 31 | 32 | case task.TaskStatusChanged: 33 | if e.Status == task.TaskStatusCompleted { 34 | t.FinishedAt = e.OccuredAt() 35 | t.Duration = t.FinishedAt.Sub(t.StartedAt) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/user/delivery.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | ) 7 | 8 | type userDelivery struct { 9 | registerUserUseCase RegisterUserUseCase 10 | } 11 | 12 | func (u *userDelivery) Register(w http.ResponseWriter, r *http.Request) { 13 | var createUserInput CreateUserInput 14 | 15 | err := json.NewDecoder(r.Body).Decode(&createUserInput) 16 | if err != nil { 17 | http.Error(w, err.Error(), http.StatusBadRequest) 18 | return 19 | } 20 | 21 | newUser, err := u.registerUserUseCase.Execute(r.Context(), createUserInput) 22 | if err != nil { 23 | http.Error(w, err.Error(), http.StatusBadRequest) 24 | return 25 | } 26 | 27 | w.Header().Set("Content-Type", "application/json") 28 | w.WriteHeader(http.StatusCreated) 29 | json.NewEncoder(w).Encode(newUser) 30 | } 31 | 32 | func (u *userDelivery) DeleteAccount(w http.ResponseWriter, r *http.Request) { 33 | // TODO 34 | } 35 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | kong-plugin-builder: 5 | build: . 6 | image: kong-plugin-builder 7 | tty: true 8 | stdin_open: true 9 | volumes: 10 | - .:/tmp/go-plugins 11 | kong: 12 | image: kong:2.3.3-alpine 13 | environment: 14 | - KONG_DATABASE=off 15 | - KONG_DECLARATIVE_CONFIG=/usr/local/kong/config.yml 16 | - KONG_PLUGINS=bundled,key-checker 17 | - KONG_PLUGINSERVER_NAMES=key-checker 18 | - KONG_PLUGINSERVER_KEY_CHECKER_START_CMD=/usr/local/kong/go-plugins/bin/key-checker 19 | - KONG_PLUGINSERVER_KEY_CHECKER_QUERY_CMD=/usr/local/kong/go-plugins/bin/key-checker -dump 20 | - KONG_PROXY_LISTEN=0.0.0.0:8000 21 | - KONG_LOG_LEVEL=debug 22 | ports: 23 | - '8000:8000' 24 | restart: on-failure 25 | volumes: 26 | - ./config.yml:/usr/local/kong/config.yml 27 | - .:/usr/local/kong/go-plugins 28 | 29 | volumes: 30 | shared-volume: 31 | 32 | -------------------------------------------------------------------------------- /src/etc/demo-kong-plugin/internal/domain/usecase/keychecker/validate_key_use_case.go: -------------------------------------------------------------------------------- 1 | package keychecker 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | keycheckerentity "github.com/syafdia/demo-kong-plugin/internal/domain/entity/keychecker" 8 | ) 9 | 10 | type ValidateKeyUseCase interface { 11 | Execute(ctx context.Context, forwardInput keycheckerentity.ValidateKeyInput) error 12 | } 13 | 14 | type validateKeyUseCase struct{} 15 | 16 | func NewValidateKeyUseCase() ValidateKeyUseCase { 17 | return &validateKeyUseCase{} 18 | } 19 | 20 | func (v *validateKeyUseCase) Execute(ctx context.Context, forwardInput keycheckerentity.ValidateKeyInput) error { 21 | log.Println("[ValidateKeyUseCase] Start validate key use case") 22 | 23 | if forwardInput.GivenKey == "" { 24 | return keycheckerentity.ErrKeyEmpty 25 | } 26 | 27 | if forwardInput.GivenKey != forwardInput.ValidKey { 28 | return keycheckerentity.ErrKeyNotValid 29 | } 30 | 31 | log.Println("[ValidateKeyUseCase] Key is valid") 32 | 33 | return nil 34 | } 35 | -------------------------------------------------------------------------------- /src/etc/demo-nats/pubsub/publisher/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | "github.com/nats-io/nats.go" 10 | "github.com/nats-io/nats.go/jetstream" 11 | ) 12 | 13 | func main() { 14 | nc, err := nats.Connect(nats.DefaultURL) 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | js, err := jetstream.New(nc) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 25 | defer cancel() 26 | 27 | log.Println("[publisher] Will publish some messages") 28 | 29 | js.Publish(ctx, "hi.joe", buildGreetPayload("Joe")) 30 | time.Sleep(1 * time.Second) 31 | 32 | js.Publish(ctx, "hi.john", buildGreetPayload("John")) 33 | time.Sleep(1 * time.Second) 34 | 35 | js.Publish(ctx, "hi.doe", buildGreetPayload("Doe")) 36 | time.Sleep(1 * time.Second) 37 | 38 | log.Println("[publisher] Messages has been published") 39 | } 40 | 41 | func buildGreetPayload(name string) []byte { 42 | return []byte(fmt.Sprintf("Hello %s, %d", name, time.Now().Unix())) 43 | } 44 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/source/business_repo.go: -------------------------------------------------------------------------------- 1 | package source 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/syafdia/xaam/internal/domain/entity" 7 | be "github.com/syafdia/xaam/internal/domain/entity/business" 8 | "github.com/syafdia/xaam/internal/domain/repo" 9 | ) 10 | 11 | type businessRepo struct { 12 | } 13 | 14 | var businessIDWithBusiness = map[string]be.GetOneResponse{ 15 | "abcd-0001-56789-asdf": { 16 | BusinessID: "abcd-0001-56789-asdf", 17 | CountryID: "ID", 18 | IndustryID: 1, 19 | LegalEntityID: 1, 20 | }, 21 | "abcd-0002-56789-asdf": { 22 | BusinessID: "abcd-0002-56789-asdf", 23 | CountryID: "ID", 24 | IndustryID: 2, 25 | LegalEntityID: 2, 26 | }, 27 | } 28 | 29 | func NewBusinessRepo() repo.BusinessRepo { 30 | return &businessRepo{} 31 | } 32 | 33 | func (b *businessRepo) FindOneByBusinessID(ctx context.Context, businessID string) (be.GetOneResponse, error) { 34 | resp, ok := businessIDWithBusiness[businessID] 35 | if !ok { 36 | return be.GetOneResponse{}, entity.ErrNotFound 37 | } 38 | 39 | return resp, nil 40 | } 41 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/source/resource_action_repo.go: -------------------------------------------------------------------------------- 1 | package source 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/jmoiron/sqlx" 7 | e "github.com/syafdia/xaam/internal/domain/entity" 8 | "github.com/syafdia/xaam/internal/domain/repo" 9 | ) 10 | 11 | const ( 12 | sqlFindMultipleByIDandTargetType = ` 13 | SELECT 14 | ra.id, 15 | ra.resource_id, 16 | ra.name 17 | FROM target_resource_actions tra 18 | JOIN resource_actions ra ON ra.id = tra.resource_action_id 19 | WHERE tra.target_id = $1 AND tra.target_type = $2; 20 | ` 21 | ) 22 | 23 | type PolicyRepo struct { 24 | db *sqlx.DB 25 | } 26 | 27 | func NewPolicyRepo(db *sqlx.DB) repo.PolicyRepo { 28 | return &PolicyRepo{db: db} 29 | } 30 | 31 | func (r *PolicyRepo) FindMultipleByIDandTargetType( 32 | ctx context.Context, 33 | targetID int64, 34 | targetType e.TargetType, 35 | ) ([]e.Action, error) { 36 | results := []e.Action{} 37 | err := r.db.SelectContext(ctx, &results, sqlFindMultipleByIDandTargetType, targetID, targetType) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return results, nil 43 | } 44 | -------------------------------------------------------------------------------- /src/distributed/semaphore/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "time" 7 | 8 | "github.com/go-redis/redis/v8" 9 | "github.com/syafdia/distributed/semaphore" 10 | ) 11 | 12 | func main() { 13 | redisClient := redis.NewClient(&redis.Options{ 14 | Addr: "localhost:6379", 15 | }) 16 | 17 | sem, err := semaphore.New(20, "example", redisClient, 2*time.Minute) 18 | if err != nil { 19 | panic(err) 20 | } 21 | 22 | totalProceses := 11 23 | for i := 0; i < totalProceses; i++ { 24 | n := i 25 | go runHeavyProcess(sem, n) 26 | } 27 | 28 | waitForeverC := make(chan bool, 1) 29 | <-waitForeverC 30 | } 31 | 32 | func runHeavyProcess(sem *semaphore.Semaphore, n int) { 33 | ctx := context.Background() 34 | 35 | resource, err := sem.Acquire(ctx) 36 | if err != nil { 37 | fmt.Println("Got error", err) 38 | return 39 | } 40 | 41 | fmt.Println("Heavy process started, id:", n) 42 | time.Sleep(10 * time.Second) 43 | fmt.Println("Heavy process finished, id:", n) 44 | 45 | err = sem.Release(ctx, resource) 46 | if err != nil { 47 | fmt.Println("Got error", err) 48 | return 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/concurrency/workerpool/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "runtime" 6 | "time" 7 | 8 | "github.com/syafdia/go-exercise/src/concurrency/workerpool" 9 | ) 10 | 11 | func main() { 12 | log.SetFlags(log.Ltime) 13 | 14 | // For monitoring purpose. 15 | waitC := make(chan bool) 16 | go func() { 17 | for { 18 | log.Printf("[main] Total current goroutine: %d", runtime.NumGoroutine()) 19 | time.Sleep(1 * time.Second) 20 | } 21 | }() 22 | 23 | // Start Worker Pool. 24 | totalWorker := 5 25 | wp := workerpool.NewWorkerPool(totalWorker) 26 | wp.Run() 27 | 28 | type result struct { 29 | id int 30 | value int 31 | } 32 | 33 | totalTask := 100 34 | resultC := make(chan result, totalTask) 35 | 36 | for i := 0; i < totalTask; i++ { 37 | id := i + 1 38 | wp.AddTask(func() { 39 | log.Printf("[main] Starting task %d", id) 40 | time.Sleep(5 * time.Second) 41 | resultC <- result{id, id * 2} 42 | }) 43 | } 44 | 45 | for i := 0; i < totalTask; i++ { 46 | res := <-resultC 47 | log.Printf("[main] Task %d has been finished with result %d", res.id, res.value) 48 | } 49 | 50 | <-waitC 51 | } 52 | -------------------------------------------------------------------------------- /src/etc/demo-nats/go.sum: -------------------------------------------------------------------------------- 1 | github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= 2 | github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 3 | github.com/nats-io/nats.go v1.36.0 h1:suEUPuWzTSse/XhESwqLxXGuj8vGRuPRoG7MoRN/qyU= 4 | github.com/nats-io/nats.go v1.36.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= 5 | github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= 6 | github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= 7 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 8 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 9 | golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= 10 | golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= 11 | golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= 12 | golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 13 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 14 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 15 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/pipeline_test.go: -------------------------------------------------------------------------------- 1 | package pipeline 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_pipeline_Pipe(t *testing.T) { 8 | type fields struct { 9 | dataC chan interface{} 10 | errC chan error 11 | executors []Executor 12 | } 13 | type args struct { 14 | executor Executor 15 | } 16 | tests := []struct { 17 | name string 18 | fields fields 19 | args args 20 | check func(f fields) bool 21 | }{ 22 | { 23 | name: "should success adding executor to executors", 24 | fields: fields{ 25 | executors: []Executor{}, 26 | }, 27 | args: args{ 28 | executor: func(in interface{}) (interface{}, error) { 29 | return 1, nil 30 | }, 31 | }, 32 | check: func(f fields) bool { 33 | return len(f.executors) == 1 34 | }, 35 | }, 36 | } 37 | for _, tt := range tests { 38 | t.Run(tt.name, func(t *testing.T) { 39 | p := &pipeline{ 40 | dataC: tt.fields.dataC, 41 | errC: tt.fields.errC, 42 | executors: tt.fields.executors, 43 | } 44 | p.Pipe(tt.args.executor) 45 | if !tt.check(fields{p.dataC, p.errC, p.executors}) { 46 | t.Errorf("pipeline.Pipe() not run as expected") 47 | } 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/article/usecase.go: -------------------------------------------------------------------------------- 1 | package article 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/syafdia/demo-unit-test/internal/user" 7 | ) 8 | 9 | type WriteArticleUseCase interface { 10 | Execute(ctx context.Context, input CreateArticleInput) (ArticleWithAuthor, error) 11 | } 12 | 13 | type writeArticleUseCase struct { 14 | articleRepo ArticleRepo 15 | userRepo user.UserRepo 16 | } 17 | 18 | func NewWriteArticleUseCase( 19 | articleRepo ArticleRepo, 20 | userRepo user.UserRepo, 21 | ) WriteArticleUseCase { 22 | return &writeArticleUseCase{ 23 | articleRepo: articleRepo, 24 | userRepo: userRepo, 25 | } 26 | } 27 | 28 | func (w *writeArticleUseCase) Execute( 29 | ctx context.Context, 30 | input CreateArticleInput, 31 | ) (ArticleWithAuthor, error) { 32 | article, err := w.articleRepo.Create(ctx, input) 33 | if err != nil { 34 | return ArticleWithAuthor{}, err 35 | } 36 | 37 | author, err := w.userRepo.FindOneByID(ctx, article.UserID) 38 | if err != nil { 39 | return ArticleWithAuthor{}, err 40 | } 41 | 42 | return ArticleWithAuthor{ 43 | Article: article, 44 | UserFirstName: author.FirstName, 45 | UserLastName: author.LastName, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/application/projection_handler.go: -------------------------------------------------------------------------------- 1 | package application 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/syafdia/demo-es/internal/domain" 7 | "github.com/syafdia/demo-es/internal/domain/report" 8 | "github.com/syafdia/demo-es/internal/domain/task" 9 | ) 10 | 11 | type ProjectionHandler struct { 12 | reportRepository report.ReportRepository 13 | } 14 | 15 | func (c *ProjectionHandler) ReceiveEvent(ctx context.Context, event domain.Event) error { 16 | switch e := event.(type) { 17 | case task.TaskCreated: 18 | tr := report.NewTaskReport() 19 | 20 | tr.TaskID = e.ID 21 | tr.TaskTitle = e.Title 22 | tr.StartedAt = e.OccuredAt() 23 | 24 | err := c.reportRepository.Store(ctx, tr) 25 | if err != nil { 26 | return err 27 | } 28 | 29 | case task.TaskStatusChanged: 30 | tr, err := c.reportRepository.FindByTaskID(ctx, e.ID) 31 | if err != nil { 32 | return err 33 | } 34 | 35 | if e.Status != task.TaskStatusCompleted { 36 | break 37 | } 38 | 39 | tr.FinishedAt = e.OccuredAt() 40 | tr.Duration = tr.FinishedAt.Sub(tr.StartedAt) 41 | 42 | err = c.reportRepository.Update(ctx, tr) 43 | if err != nil { 44 | return err 45 | } 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /src/etc/demo-nats/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | nats-1: 4 | container_name: nats-1 5 | image: nats 6 | entrypoint: /nats-server 7 | command: --server_name N1 --cluster_name JSC --js --sd /data --cluster nats://0.0.0.0:4245 --routes nats://nats-2:4245,nats://nats-3:4245 -p 4222 8 | networks: 9 | - demo-nats-network 10 | ports: 11 | - 4222:4222 12 | 13 | nats-2: 14 | container_name: nats-2 15 | image: nats 16 | entrypoint: /nats-server 17 | command: --server_name N2 --cluster_name JSC --js --sd /data --cluster nats://0.0.0.0:4245 --routes nats://nats-1:4245,nats://nats-3:4245 -p 4222 18 | networks: 19 | - demo-nats-network 20 | ports: 21 | - 4223:4222 22 | 23 | nats-3: 24 | container_name: nats-3 25 | image: nats 26 | entrypoint: /nats-server 27 | command: --server_name N3 --cluster_name JSC --js --sd /data --cluster nats://0.0.0.0:4245 --routes nats://nats-1:4245,nats://nats-2:4245 -p 4222 28 | networks: 29 | - demo-nats-network 30 | ports: 31 | - 4224:4222 32 | 33 | networks: 34 | demo-nats-network: 35 | driver: bridge 36 | ipam: 37 | config: 38 | - subnet: 172.22.0.0/24 39 | volumes: 40 | hydra-sqlite: -------------------------------------------------------------------------------- /src/concurrency/workerpool/worker_pool.go: -------------------------------------------------------------------------------- 1 | package workerpool 2 | 3 | import ( 4 | "log" 5 | ) 6 | 7 | // WorkerPool is a contract for Worker Pool implementation 8 | type WorkerPool interface { 9 | Run() 10 | AddTask(task func()) 11 | } 12 | 13 | type workerPool struct { 14 | maxWorker int 15 | queuedTaskC chan func() 16 | } 17 | 18 | // NewWorkerPool will create an instance of WorkerPool. 19 | func NewWorkerPool(maxWorker int) WorkerPool { 20 | wp := &workerPool{ 21 | maxWorker: maxWorker, 22 | queuedTaskC: make(chan func()), 23 | } 24 | 25 | return wp 26 | } 27 | 28 | func (wp *workerPool) Run() { 29 | wp.run() 30 | } 31 | 32 | func (wp *workerPool) AddTask(task func()) { 33 | wp.queuedTaskC <- task 34 | } 35 | 36 | func (wp *workerPool) GetTotalQueuedTask() int { 37 | return len(wp.queuedTaskC) 38 | } 39 | 40 | func (wp *workerPool) run() { 41 | for i := 0; i < wp.maxWorker; i++ { 42 | wID := i + 1 43 | log.Printf("[WorkerPool] Worker %d has been spawned", wID) 44 | 45 | go func(workerID int) { 46 | for task := range wp.queuedTaskC { 47 | log.Printf("[WorkerPool] Worker %d start processing task", wID) 48 | task() 49 | log.Printf("[WorkerPool] Worker %d finish processing task", wID) 50 | } 51 | }(wID) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/etc/XAAM/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/xaam 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.7.7 7 | github.com/jmoiron/sqlx v1.3.4 8 | ) 9 | 10 | require ( 11 | github.com/google/go-querystring v1.1.0 // indirect 12 | github.com/joho/godotenv v1.4.0 // indirect 13 | ) 14 | 15 | require ( 16 | github.com/dghubble/sling v1.4.0 17 | github.com/gin-contrib/sse v0.1.0 // indirect 18 | github.com/go-playground/locales v0.13.0 // indirect 19 | github.com/go-playground/universal-translator v0.17.0 // indirect 20 | github.com/go-playground/validator/v10 v10.4.1 // indirect 21 | github.com/golang/mock v1.6.0 22 | github.com/golang/protobuf v1.3.3 // indirect 23 | github.com/json-iterator/go v1.1.9 // indirect 24 | github.com/leodido/go-urn v1.2.0 // indirect 25 | github.com/lib/pq v1.10.4 26 | github.com/mattn/go-isatty v0.0.12 // indirect 27 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 28 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 // indirect 29 | github.com/ugorji/go/codec v1.1.7 // indirect 30 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect 31 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect 32 | gopkg.in/yaml.v2 v2.2.8 // indirect 33 | ) 34 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/infrastructure/base/centralized-log/logstash.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: logstash.k8s.elastic.co/v1alpha1 2 | kind: Logstash 3 | metadata: 4 | name: centralized-log-ls 5 | namespace: centralized-log 6 | spec: 7 | count: 1 8 | version: 8.9.0 9 | elasticsearchRefs: 10 | - clusterName: centralized-log-es 11 | name: default-nodes 12 | pipelines: 13 | - pipeline.id: main 14 | config.string: | 15 | input { 16 | beats { 17 | port => 5044 18 | } 19 | } 20 | filter { 21 | grok { 22 | match => { "message" => "%{HTTPD_COMMONLOG}"} 23 | } 24 | geoip { 25 | source => "[source][address]" 26 | target => "[source]" 27 | } 28 | } 29 | output { 30 | elasticsearch { 31 | hosts => [ "${ECK_ES_HOSTS}" ] 32 | user => "${ECK_ES_USER}" 33 | password => "${ECK_ES_PASSWORD}" 34 | ssl_certificate_authorities => "${ECK_ES_SSL_CERTIFICATE_AUTHORITY}" 35 | } 36 | } 37 | services: 38 | - name: beats 39 | service: 40 | spec: 41 | type: ClusterIP 42 | ports: 43 | - port: 5044 44 | targetPort: 5044 -------------------------------------------------------------------------------- /src/etc/demo-oauth2/internal/auth/handlers.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | type AuthHandler struct { 10 | repo *Repo 11 | client *Client 12 | } 13 | 14 | func NewAuthHandler(repo *Repo, client *Client) *AuthHandler { 15 | return &AuthHandler{ 16 | repo: repo, 17 | client: client, 18 | } 19 | } 20 | 21 | func (a *AuthHandler) NewSession(c *gin.Context) { 22 | c.HTML(http.StatusOK, "session.new", map[string]interface{}{ 23 | "LoginChallenge": c.Query("login_challenge"), 24 | }) 25 | } 26 | 27 | func (a *AuthHandler) CreateSession(c *gin.Context) { 28 | username := c.Request.FormValue("username") 29 | password := c.Request.FormValue("password") 30 | // loginChallenge := c.Request.FormValue("login_challenge") 31 | 32 | user, err := a.repo.User.FindByUsernameAndPassword(c, username, password) 33 | if err != nil { 34 | c.JSON(http.StatusUnauthorized, map[string]interface{}{ 35 | "error": err, 36 | }) 37 | return 38 | } 39 | 40 | c.JSON(http.StatusOK, map[string]interface{}{ 41 | // TODO: render token 42 | "username": user.Username, 43 | }) 44 | } 45 | 46 | func (a *AuthHandler) NewConsent(c *gin.Context) { 47 | 48 | } 49 | 50 | func (a *AuthHandler) CreateConsent(c *gin.Context) { 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/k8s/demo-helm/charts/calculator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: calculator 3 | description: A Helm chart for Kubernetes for deploying go-calculator app 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "1.16.0" 25 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/pipeline.go: -------------------------------------------------------------------------------- 1 | package pipeline 2 | 3 | type Executor func(interface{}) (interface{}, error) 4 | 5 | type Pipeline interface { 6 | Pipe(executor Executor) Pipeline 7 | Merge() <-chan interface{} 8 | } 9 | 10 | type pipeline struct { 11 | dataC chan interface{} 12 | errC chan error 13 | executors []Executor 14 | } 15 | 16 | func New(f func(chan interface{})) Pipeline { 17 | inC := make(chan interface{}) 18 | 19 | go f(inC) 20 | 21 | return &pipeline{ 22 | dataC: inC, 23 | errC: make(chan error), 24 | executors: []Executor{}, 25 | } 26 | } 27 | 28 | func (p *pipeline) Pipe(executor Executor) Pipeline { 29 | p.executors = append(p.executors, executor) 30 | 31 | return p 32 | } 33 | 34 | func (p *pipeline) Merge() <-chan interface{} { 35 | for i := 0; i < len(p.executors); i++ { 36 | p.dataC, p.errC = run(p.dataC, p.executors[i]) 37 | } 38 | 39 | return p.dataC 40 | } 41 | 42 | func run(inC <-chan interface{}, f Executor) (chan interface{}, chan error) { 43 | outC := make(chan interface{}) 44 | errC := make(chan error) 45 | 46 | go func() { 47 | defer close(outC) 48 | for v := range inC { 49 | res, err := f(v) 50 | if err != nil { 51 | errC <- err 52 | continue 53 | } 54 | 55 | outC <- res 56 | } 57 | }() 58 | 59 | return outC, errC 60 | } 61 | -------------------------------------------------------------------------------- /src/etc/XAAM/files/sql/0001.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE resources ( 2 | id SERIAL PRIMARY KEY, 3 | name VARCHAR (64) UNIQUE NOT NULL, 4 | created_at TIMESTAMP NOT NULL, 5 | updated_at TIMESTAMP 6 | ); 7 | 8 | CREATE TABLE resource_actions ( 9 | id SERIAL PRIMARY KEY, 10 | name VARCHAR (64) NOT NULL, 11 | resource_id BIGINT NOT NULL, 12 | created_at TIMESTAMP NOT NULL, 13 | updated_at TIMESTAMP 14 | ); 15 | 16 | CREATE INDEX idx_resource_id ON resource_actions(resource_id); 17 | CREATE INDEX idx_name ON resource_actions(name); 18 | 19 | ALTER TABLE resource_actions ADD CONSTRAINT fk_resource_id FOREIGN KEY (resource_id) REFERENCES resources(id); 20 | 21 | CREATE TYPE TARGET_TYPE AS ENUM ('legal_entity', 'industry'); 22 | 23 | CREATE TABLE target_resource_actions ( 24 | id SERIAL PRIMARY KEY, 25 | resource_action_id BIGINT NOT NULL, 26 | target_id BIGINT NOT NULL, 27 | target_type TARGET_TYPE NOT NULL, 28 | created_at TIMESTAMP NOT NULL, 29 | updated_at TIMESTAMP 30 | ); 31 | 32 | CREATE INDEX idx_resource_action_id ON target_resource_actions(resource_action_id); 33 | CREATE INDEX idx_target_id ON target_resource_actions(target_id); 34 | CREATE INDEX idx_target_type ON target_resource_actions(target_type); 35 | 36 | ALTER TABLE target_resource_actions ADD CONSTRAINT fk_resource_action_id FOREIGN KEY (resource_action_id) REFERENCES resource_actions(id); -------------------------------------------------------------------------------- /src/etc/demo-nats/pubsub/consumer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "time" 8 | 9 | "github.com/nats-io/nats.go" 10 | "github.com/nats-io/nats.go/jetstream" 11 | ) 12 | 13 | func main() { 14 | nc, err := nats.Connect(nats.DefaultURL) 15 | handleError(err) 16 | 17 | js, err := jetstream.New(nc) 18 | handleError(err) 19 | 20 | ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) 21 | defer cancel() 22 | 23 | // get existing stream handle 24 | s, err := js.CreateOrUpdateStream(ctx, jetstream.StreamConfig{ 25 | Name: "HI_STREAM", 26 | Subjects: []string{"hi.*"}, 27 | }) 28 | handleError(err) 29 | 30 | // retrieve consumer handle from a stream 31 | cons, err := s.CreateOrUpdateConsumer(ctx, jetstream.ConsumerConfig{ 32 | Durable: "HI_CONSUMER", 33 | AckPolicy: jetstream.AckExplicitPolicy, 34 | }) 35 | handleError(err) 36 | 37 | log.Println("[publisher] Will consume from callback") 38 | 39 | cc, err := cons.Consume(func(msg jetstream.Msg) { 40 | log.Println("[consumer] Receive message via consume:", string(msg.Data())) 41 | msg.Ack() 42 | }) 43 | handleError(err) 44 | 45 | defer cc.Stop() 46 | 47 | waitC := make(chan int, 1) 48 | <-waitC 49 | } 50 | 51 | func handleError(err error) { 52 | if err != nil { 53 | panic(fmt.Sprintf("[consumer]: got error, error: %s", err)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/example/e00/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | 7 | "github.com/syafdia/go-exercise/src/concurrency/pipeline" 8 | "github.com/syafdia/go-exercise/src/concurrency/pipeline/example" 9 | ) 10 | 11 | func main() { 12 | N := 5 13 | startTime := time.Now() 14 | 15 | for i := 0; i < N; i++ { 16 | result := example.AddFoo(example.AddQuoute(example.Square(example.MultiplyTwo(i)))) 17 | fmt.Printf("Result: %s\n", result) 18 | } 19 | 20 | fmt.Printf("Elapsed time without concurrency: %s", time.Since(startTime)) // ~40 seconds 21 | 22 | outC := pipeline.New(func(inC chan interface{}) { 23 | defer close(inC) 24 | for i := 0; i < N; i++ { 25 | inC <- i 26 | } 27 | }). 28 | Pipe(func(in interface{}) (interface{}, error) { 29 | return example.MultiplyTwo(in.(int)), nil 30 | }). 31 | Pipe(func(in interface{}) (interface{}, error) { 32 | return example.Square(in.(int)), nil 33 | }). 34 | Pipe(func(in interface{}) (interface{}, error) { 35 | return example.AddQuoute(in.(int)), nil 36 | }). 37 | Pipe(func(in interface{}) (interface{}, error) { 38 | return example.AddFoo(in.(string)), nil 39 | }). 40 | Merge() 41 | 42 | startTimeC := time.Now() 43 | for result := range outC { 44 | fmt.Printf("Result: %s\n", result) 45 | } 46 | 47 | fmt.Printf("Elapsed time with concurrency: %s", time.Since(startTimeC)) // ~16 seconds 48 | } 49 | -------------------------------------------------------------------------------- /src/concurrency/pipeline/pipeline_bench_test.go: -------------------------------------------------------------------------------- 1 | package pipeline 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | "time" 7 | ) 8 | 9 | func BenchmarkWithPipelineModule(b *testing.B) { 10 | outC := New(func(inC chan interface{}) { 11 | defer close(inC) 12 | for i := 0; i < b.N; i++ { 13 | inC <- i 14 | } 15 | }). 16 | Pipe(func(in interface{}) (interface{}, error) { 17 | return multiplyTwo(in.(int)), nil 18 | }). 19 | Pipe(func(in interface{}) (interface{}, error) { 20 | return square(in.(int)), nil 21 | }). 22 | Pipe(func(in interface{}) (interface{}, error) { 23 | return addQuoute(in.(int)), nil 24 | }). 25 | Pipe(func(in interface{}) (interface{}, error) { 26 | return addFoo(in.(string)), nil 27 | }). 28 | Merge() 29 | 30 | for range outC { 31 | // Do nothing, just for drain out channel 32 | } 33 | } 34 | 35 | func BenchmarkWithoutPipelineModule(b *testing.B) { 36 | for i := 0; i < b.N; i++ { 37 | addFoo(addQuoute(square(multiplyTwo(i)))) 38 | } 39 | } 40 | 41 | func multiplyTwo(v int) int { 42 | time.Sleep(100 * time.Millisecond) 43 | return v * 2 44 | } 45 | 46 | func square(v int) int { 47 | time.Sleep(200 * time.Millisecond) 48 | return v * v 49 | } 50 | 51 | func addQuoute(v int) string { 52 | time.Sleep(100 * time.Millisecond) 53 | return fmt.Sprintf("'%d'", v) 54 | } 55 | 56 | func addFoo(v string) string { 57 | time.Sleep(200 * time.Millisecond) 58 | return fmt.Sprintf("%s - Foo", v) 59 | } 60 | -------------------------------------------------------------------------------- /src/k8s/demo-flux/clusters/development/infrastructure.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.toolkit.fluxcd.io/v1 2 | kind: Kustomization 3 | metadata: 4 | name: elastic-system 5 | namespace: flux-system 6 | spec: 7 | interval: 1m0s 8 | sourceRef: 9 | kind: GitRepository 10 | name: flux-system 11 | path: ./src/k8s/demo-flux/infrastructure/base/elastic-system 12 | prune: true 13 | --- 14 | # Temporarily disable this apps since thhis apps consume large amount of memory. 15 | # 16 | # apiVersion: kustomize.toolkit.fluxcd.io/v1 17 | # kind: Kustomization 18 | # metadata: 19 | # name: centralized-log 20 | # namespace: flux-system 21 | # spec: 22 | # interval: 1m0s 23 | # sourceRef: 24 | # kind: GitRepository 25 | # name: flux-system 26 | # path: ./src/k8s/demo-flux/infrastructure/base/centralized-log 27 | # prune: true 28 | # --- 29 | apiVersion: kustomize.toolkit.fluxcd.io/v1 30 | kind: Kustomization 31 | metadata: 32 | name: gloo-system 33 | namespace: flux-system 34 | spec: 35 | interval: 1m0s 36 | sourceRef: 37 | kind: GitRepository 38 | name: flux-system 39 | path: ./src/k8s/demo-flux/infrastructure/base/gloo-system 40 | prune: true 41 | --- 42 | apiVersion: kustomize.toolkit.fluxcd.io/v1 43 | kind: Kustomization 44 | metadata: 45 | name: flagger 46 | namespace: flux-system 47 | spec: 48 | interval: 1m0s 49 | sourceRef: 50 | kind: GitRepository 51 | name: flux-system 52 | path: ./src/k8s/demo-flux/infrastructure/base/flagger 53 | prune: true -------------------------------------------------------------------------------- /src/etc/demo-oauth2/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.5' 2 | services: 3 | 4 | hydra-postgres: 5 | image: 'postgres:15' 6 | environment: 7 | POSTGRES_USER: postgres 8 | POSTGRES_PASSWORD: postgres 9 | ports: 10 | - '5432:5432' 11 | tty: true 12 | volumes: 13 | - ./volumes/postgresql/var/lib/postgresql/data:/var/lib/postgresql/data 14 | 15 | hydra-migrate: 16 | image: 'oryd/hydra:v2.3.0' 17 | restart: on-failure 18 | command: 19 | migrate sql -e --yes 20 | environment: 21 | - DSN=postgres://postgres:postgres@hydra-postgres:5432/postgres?sslmode=disable&max_conns=20&max_idle_conns=4 22 | depends_on: 23 | - hydra-postgres 24 | 25 | hydra-core: 26 | image: 'oryd/hydra:v2.3.0' 27 | environment: 28 | - DSN=postgres://postgres:postgres@hydra-postgres:5432/postgres?sslmode=disable&max_conns=20&max_idle_conns=4 29 | - SECRETS_SYSTEM=my-secret-my-secret-my-secret 30 | - URLS_LOGIN=http://localhost:9001/auth/session/new # Sets the login endpoint of the User Login & Consent flow. 31 | - URLS_CONSENT=http://localhost:9001/auth/consent/new # Sets the consent endpoint of the User Login & Consent flow. 32 | - SERVE_PUBLIC_PORT=4444 33 | - SERVE_PUBLIC_HOST=0.0.0.0 34 | - SERVE_PUBLIC_CORS_ENABLED=true 35 | - SERVE_ADMIN_PORT=4445 36 | - LOG_LEVEL=debug 37 | ports: 38 | - '4444:4444' # Public port 39 | - '4445:4445' # Admin port 40 | - '5555:5555' # Port for debug app 41 | tty: true -------------------------------------------------------------------------------- /src/etc/XAAM/e2e/api_v1_authotrisation_check_test.go: -------------------------------------------------------------------------------- 1 | package e2e 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | "reflect" 7 | "testing" 8 | 9 | "github.com/dghubble/sling" 10 | ) 11 | 12 | func Test_PostAPIV1AuthorisationCheck_400(t *testing.T) { 13 | client := &http.Client{} 14 | req, _ := sling.New().Post("http://0.0.0.0:8080/api/v1/authorisation/check").Request() 15 | 16 | resp, _ := client.Do(req) 17 | defer resp.Body.Close() 18 | 19 | if !reflect.DeepEqual(resp.StatusCode, http.StatusBadRequest) { 20 | t.Errorf("http status is not 400, got %d", resp.StatusCode) 21 | } 22 | } 23 | 24 | func Test_PostAPIV1AuthorisationCheck_200(t *testing.T) { 25 | client := &http.Client{} 26 | req, _ := sling.New(). 27 | Post("http://0.0.0.0:8080/api/v1/authorisation/check"). 28 | BodyJSON(map[string]interface{}{ 29 | "actions": []string{"compliant"}, 30 | "resource": map[string]interface{}{ 31 | "kind": "VA", 32 | }, 33 | "principal": map[string]interface{}{ 34 | "kind": "BUSINESS_ID", 35 | "id": "abcd-0001-56789-asdf", 36 | }, 37 | }). 38 | Request() 39 | 40 | resp, _ := client.Do(req) 41 | defer resp.Body.Close() 42 | 43 | if !reflect.DeepEqual(resp.StatusCode, http.StatusOK) { 44 | t.Errorf("http status is not 200, got %d", resp.StatusCode) 45 | } 46 | 47 | rawBody, _ := ioutil.ReadAll(resp.Body) 48 | expectedBody := `{"results":[{"kind":"VA","actions":{"compliant":"EFFECT_ALLOWED"}}]}` 49 | 50 | if !reflect.DeepEqual(string(rawBody), expectedBody) { 51 | t.Errorf("response body is not valid,, got %s", expectedBody) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/etc/demo-unit-test/internal/user/repo.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/jmoiron/sqlx" 7 | ) 8 | 9 | type UserRepo interface { 10 | Create(ctx context.Context, input CreateUserInput) (User, error) 11 | Update(ctx context.Context, input UpdateUserInput) (User, error) 12 | FindOneByID(ctx context.Context, id int64) (User, error) 13 | Destroy(ctx context.Context, id int64) error 14 | } 15 | 16 | type userRepo struct { 17 | db *sqlx.DB 18 | } 19 | 20 | func NewUserRepo(db *sqlx.DB) UserRepo { 21 | return &userRepo{db: db} 22 | } 23 | 24 | func (u *userRepo) Create(ctx context.Context, input CreateUserInput) (User, error) { 25 | result, err := u.db.ExecContext(ctx, 26 | `INSERT INTO users (email, first_name, last_name, gender) VALUES ($1, $2, $3, $4);`, 27 | input.Email, 28 | input.FirstName, 29 | input.LastName, 30 | input.Gender) 31 | if err != nil { 32 | return User{}, err 33 | } 34 | 35 | userID, err := result.LastInsertId() 36 | if err != nil { 37 | return User{}, err 38 | } 39 | 40 | return User{ 41 | ID: userID, 42 | Email: input.Email, 43 | FirstName: input.FirstName, 44 | LastName: input.LastName, 45 | Gender: input.Gender, 46 | }, nil 47 | } 48 | 49 | func (u *userRepo) Update(ctx context.Context, input UpdateUserInput) (User, error) { 50 | // TODO 51 | return User{}, nil 52 | } 53 | 54 | func (u *userRepo) FindOneByID(ctx context.Context, id int64) (User, error) { 55 | return User{}, nil 56 | } 57 | 58 | func (u *userRepo) Destroy(ctx context.Context, id int64) error { 59 | // TODO 60 | return nil 61 | } 62 | -------------------------------------------------------------------------------- /src/etc/XAAM/internal/delivery/auth_check_handler.go: -------------------------------------------------------------------------------- 1 | package delivery 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/syafdia/xaam/internal/di" 8 | "github.com/syafdia/xaam/internal/domain/entity" 9 | ae "github.com/syafdia/xaam/internal/domain/entity/auth" 10 | ) 11 | 12 | func PostAuthorisationHandler(useCaseModule di.UseCaseModule) gin.HandlerFunc { 13 | return func(c *gin.Context) { 14 | request := ae.CheckRequest{} 15 | 16 | err := c.BindJSON(&request) 17 | if err != nil { 18 | handleError(c, entity.WrapErr(http.StatusBadRequest, err)) 19 | return 20 | } 21 | 22 | business, err := useCaseModule.FindOneByBusinessIDUseCase.Execute(c, request.Principal.ID) 23 | if err != nil { 24 | handleError(c, err) 25 | return 26 | } 27 | 28 | resourceWithActions, err := useCaseModule.FindResourcesByComplianceUseCase.Execute(c, ae.FindResourcesByComplianceRequest{ 29 | IndustryID: business.IndustryID, 30 | LegalEntityID: business.LegalEntityID, 31 | Resources: []string{request.Resource.Kind}, 32 | }) 33 | if err != nil { 34 | handleError(c, err) 35 | return 36 | } 37 | 38 | response := ae.CheckResponse{} 39 | 40 | for resource, resourceActions := range resourceWithActions { 41 | actions := map[string]string{} 42 | for _, ra := range resourceActions { 43 | actions[ra.Name] = "EFFECT_ALLOWED" 44 | } 45 | 46 | response.Results = append(response.Results, ae.CheckResultResponse{ 47 | Kind: resource.Name, 48 | Actions: actions, 49 | }) 50 | } 51 | 52 | c.JSON(http.StatusOK, response) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/demo-oauth2 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.10.0 7 | github.com/ory/hydra-client-go v1.11.8 8 | golang.org/x/oauth2 v0.28.0 9 | ) 10 | 11 | require ( 12 | github.com/bytedance/sonic v1.11.6 // indirect 13 | github.com/bytedance/sonic/loader v0.1.1 // indirect 14 | github.com/cloudwego/base64x v0.1.4 // indirect 15 | github.com/cloudwego/iasm v0.2.0 // indirect 16 | github.com/gabriel-vasile/mimetype v1.4.3 // indirect 17 | github.com/gin-contrib/sse v0.1.0 // indirect 18 | github.com/go-playground/locales v0.14.1 // indirect 19 | github.com/go-playground/universal-translator v0.18.1 // indirect 20 | github.com/go-playground/validator/v10 v10.20.0 // indirect 21 | github.com/goccy/go-json v0.10.2 // indirect 22 | github.com/json-iterator/go v1.1.12 // indirect 23 | github.com/klauspost/cpuid/v2 v2.2.7 // indirect 24 | github.com/leodido/go-urn v1.4.0 // indirect 25 | github.com/mattn/go-isatty v0.0.20 // indirect 26 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 27 | github.com/modern-go/reflect2 v1.0.2 // indirect 28 | github.com/pelletier/go-toml/v2 v2.2.2 // indirect 29 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 30 | github.com/ugorji/go/codec v1.2.12 // indirect 31 | golang.org/x/arch v0.8.0 // indirect 32 | golang.org/x/crypto v0.23.0 // indirect 33 | golang.org/x/net v0.25.0 // indirect 34 | golang.org/x/sys v0.20.0 // indirect 35 | golang.org/x/text v0.15.0 // indirect 36 | google.golang.org/protobuf v1.34.1 // indirect 37 | gopkg.in/yaml.v3 v3.0.1 // indirect 38 | ) 39 | -------------------------------------------------------------------------------- /src/etc/demo-redlock/example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "time" 7 | 8 | redis "github.com/go-redis/redis/v8" 9 | demoredlock "github.com/syafdia/demo-redlock" 10 | ) 11 | 12 | func main() { 13 | log.SetFlags(log.Ltime) 14 | rc1 := redis.NewClient(&redis.Options{Addr: "0.0.0.0:7001"}) 15 | rc2 := redis.NewClient(&redis.Options{Addr: "0.0.0.0:7002"}) 16 | rc3 := redis.NewClient(&redis.Options{Addr: "0.0.0.0:7003"}) 17 | 18 | dlm := demoredlock.NewDLM([]*redis.Client{rc1, rc2, rc3}, 10*time.Second, 2*time.Second) 19 | 20 | withLockOnly(dlm) 21 | } 22 | 23 | func withLockAndUnlock(dlm *demoredlock.DLM) { 24 | ctx := context.Background() 25 | locker := dlm.NewLocker("this-is-a-key-002") 26 | 27 | if err := locker.Lock(ctx); err != nil { 28 | log.Fatal("[main] Failed when locking, err:", err) 29 | } 30 | 31 | // Perform operation. 32 | someOperation() 33 | 34 | if err := locker.Unlock(ctx); err != nil { 35 | log.Fatal("[main] Failed when unlocking, err:", err) 36 | } 37 | 38 | log.Println("[main] Done") 39 | } 40 | 41 | func withLockOnly(dlm *demoredlock.DLM) { 42 | ctx := context.Background() 43 | locker := dlm.NewLocker("this-is-a-key-002") 44 | 45 | if err := locker.Lock(ctx); err != nil { 46 | log.Fatal("[main] Failed when locking, err:", err) 47 | } 48 | 49 | // Perform operation. 50 | someOperation() 51 | 52 | // Don't unlock 53 | 54 | log.Println("[main] Done") 55 | } 56 | 57 | func someOperation() { 58 | log.Println("[someOperation] Process has been started") 59 | time.Sleep(1 * time.Second) 60 | log.Println("[someOperation] Process has been finished") 61 | } 62 | -------------------------------------------------------------------------------- /src/etc/go-calculator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/syafdia/go-exercise/src/etc/go-calculator 2 | 3 | go 1.20 4 | 5 | require github.com/gin-gonic/gin v1.9.0 6 | 7 | require ( 8 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 9 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 10 | ) 11 | 12 | require ( 13 | github.com/bytedance/sonic v1.8.0 // indirect 14 | github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect 15 | github.com/gin-contrib/sse v0.1.0 // indirect 16 | github.com/go-playground/locales v0.14.1 // indirect 17 | github.com/go-playground/universal-translator v0.18.1 // indirect 18 | github.com/go-playground/validator/v10 v10.11.2 // indirect 19 | github.com/goccy/go-json v0.10.0 // indirect 20 | github.com/gorilla/websocket v1.5.3 21 | github.com/json-iterator/go v1.1.12 // indirect 22 | github.com/klauspost/cpuid/v2 v2.0.9 // indirect 23 | github.com/leodido/go-urn v1.2.1 // indirect 24 | github.com/mattn/go-isatty v0.0.17 // indirect 25 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect 26 | github.com/modern-go/reflect2 v1.0.2 // indirect 27 | github.com/pelletier/go-toml/v2 v2.0.6 // indirect 28 | github.com/redis/go-redis/v9 v9.0.5 29 | github.com/twitchyliquid64/golang-asm v0.15.1 // indirect 30 | github.com/ugorji/go/codec v1.2.9 // indirect 31 | golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect 32 | golang.org/x/crypto v0.5.0 // indirect 33 | golang.org/x/net v0.7.0 // indirect 34 | golang.org/x/sys v0.5.0 // indirect 35 | golang.org/x/text v0.7.0 // indirect 36 | google.golang.org/protobuf v1.28.1 // indirect 37 | gopkg.in/yaml.v3 v3.0.1 // indirect 38 | ) 39 | -------------------------------------------------------------------------------- /src/etc/demo-event-sourcing/internal/domain/task/events.go: -------------------------------------------------------------------------------- 1 | package task 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/syafdia/demo-es/internal/domain" 7 | ) 8 | 9 | type TaskCreated struct { 10 | ID domain.ID `json:"-"` 11 | Timestamp time.Time `json:"-"` 12 | Title string 13 | Description string 14 | Status TaskStatus 15 | } 16 | 17 | func (t TaskCreated) AggregateID() domain.ID { 18 | return t.ID 19 | } 20 | 21 | func (t TaskCreated) OccuredAt() time.Time { 22 | return t.Timestamp 23 | } 24 | 25 | type TaskStatusChanged struct { 26 | ID domain.ID `json:"-"` 27 | Timestamp time.Time `json:"-"` 28 | Status TaskStatus 29 | } 30 | 31 | func (t TaskStatusChanged) AggregateID() domain.ID { 32 | return t.ID 33 | } 34 | 35 | func (t TaskStatusChanged) OccuredAt() time.Time { 36 | return t.Timestamp 37 | } 38 | 39 | type TaskTagAdded struct { 40 | ID domain.ID `json:"-"` 41 | Timestamp time.Time `json:"-"` 42 | Tag Tag 43 | } 44 | 45 | func (t TaskTagAdded) AggregateID() domain.ID { 46 | return t.ID 47 | } 48 | 49 | func (t TaskTagAdded) OccuredAt() time.Time { 50 | return t.Timestamp 51 | } 52 | 53 | type TaskUpvoted struct { 54 | ID domain.ID `json:"-"` 55 | Timestamp time.Time `json:"-"` 56 | } 57 | 58 | func (t TaskUpvoted) AggregateID() domain.ID { 59 | return t.ID 60 | } 61 | 62 | func (t TaskUpvoted) OccuredAt() time.Time { 63 | return t.Timestamp 64 | } 65 | 66 | type TaskDownvoted struct { 67 | ID domain.ID `json:"-"` 68 | Timestamp time.Time `json:"-"` 69 | } 70 | 71 | func (t TaskDownvoted) AggregateID() domain.ID { 72 | return t.ID 73 | } 74 | 75 | func (t TaskDownvoted) OccuredAt() time.Time { 76 | return t.Timestamp 77 | } 78 | -------------------------------------------------------------------------------- /src/etc/demo-oauth2/cmd/pokedex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "html/template" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | "github.com/syafdia/demo-oauth2/internal/pokedex" 9 | "golang.org/x/oauth2" 10 | ) 11 | 12 | func newOauth2Client() *oauth2.Config { 13 | return &oauth2.Config{ 14 | RedirectURL: "http://localhost:9002/callbacks", // Pokedex App callbacks URL 15 | 16 | // For testing purpose, we hardcoded the client_id & client_secret 17 | ClientID: "client-id-my-pokedex", 18 | ClientSecret: "client-secret-my-pokedex", 19 | 20 | Scopes: []string{"offline", "pokemon:all"}, 21 | Endpoint: oauth2.Endpoint{ 22 | AuthURL: "http://localhost:4444/oauth2/auth", 23 | TokenURL: "http://localhost:4444/oauth2/token", 24 | }, 25 | } 26 | } 27 | 28 | func setupHTMLTemplate(r *gin.Engine) { 29 | r.SetHTMLTemplate(template.Must(template.New("pokemons.list").Parse(` 30 | 31 | 32 |
33 | 34 | 35 |