Skip to content

Commit c068bf2

Browse files
Merge pull request #336 from gofr-dev/release/v1.0.0
Release v1.0.0
2 parents 80cdfd4 + 1a89477 commit c068bf2

File tree

111 files changed

+7075
-386
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

111 files changed

+7075
-386
lines changed

.github/workflows/docs.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ name: Build and Deploy
33
push:
44
paths:
55
- 'docs/**'
6+
pull_request:
7+
paths:
8+
- 'docs/**'
9+
610
env:
711
APP_NAME: gofr-web
812
REGISTRY: gcr.io

.github/workflows/go.yml

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,61 @@ on:
1515
- 'docs/**'
1616

1717
jobs:
18+
MIGRATION-Unit-Testing:
19+
name: Migration Unit Testing🛠
20+
runs-on: ubuntu-latest
21+
22+
steps:
23+
- name: Checkout code into go module directory
24+
uses: actions/checkout@v4
25+
with:
26+
fetch-depth: 0
27+
28+
- name: Set up Go 1.21
29+
uses: actions/setup-go@v4
30+
with:
31+
go-version: 1.21
32+
id: Go
33+
34+
- name: Get dependencies
35+
run: |
36+
go mod download
37+
38+
- name: Test
39+
run: |
40+
export GOFR_ENV=test
41+
go test gofr.dev/pkg/gofr/migration... -v -short -coverprofile profile.cov -coverpkg=gofr.dev/pkg/gofr/migration...
42+
43+
go tool cover -func profile.cov
44+
45+
- name: Upload Test Coverage
46+
uses: actions/upload-artifact@v3
47+
with:
48+
name: MIGRATION-Coverage-Report
49+
path: profile.cov
50+
1851
Example-Unit-Testing:
1952
name: Example Unit Testing🛠
2053
runs-on: ubuntu-latest
2154
services:
55+
zookeeper:
56+
image: wurstmeister/zookeeper
57+
ports:
58+
- "2181:2181"
59+
60+
kafka:
61+
image: wurstmeister/kafka
62+
ports:
63+
- "9092:9092"
64+
env:
65+
KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://localhost:9092'
66+
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT'
67+
KAFKA_INTER_BROKER_LISTENER_NAME: 'PLAINTEXT'
68+
KAFKA_ADVERTISED_HOST_NAME: 'localhost'
69+
KAFKA_LISTENERS: 'PLAINTEXT://0.0.0.0:9092'
70+
KAFKA_AUTO_CREATE_TOPICS_ENABLE: true
71+
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
72+
2273
redis:
2374
image: redis:7.0.5
2475
ports:
@@ -49,13 +100,19 @@ jobs:
49100
run: |
50101
go mod download
51102
103+
- name: Create Kafka topics for test
104+
run: |
105+
docker exec ${{ job.services.kafka.id }} kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic products
106+
docker exec ${{ job.services.kafka.id }} kafka-topics.sh --create --bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic order-logs
107+
52108
- name: Start Zipkin
53109
run: docker run -d -p 2005:9411 openzipkin/zipkin:latest
54110

55111
- name: Test
56112
run: |
57113
export GOFR_ENV=test
58-
go test gofr.dev/examples/... -v -short -coverprofile profile.cov -coverpkg=gofr.dev/examples/...
114+
go test gofr.dev/examples/... -v -short -coverprofile packageWithpbgo.cov -coverpkg=gofr.dev/examples/...
115+
grep -vE '^gofr\.dev\/.*\.pb\.go' packageWithpbgo.cov > profile.cov
59116
go tool cover -func profile.cov
60117
61118
- name: Upload Test Coverage
@@ -87,7 +144,8 @@ jobs:
87144
- name: Test
88145
run: |
89146
export GOFR_ENV=test
90-
go test gofr.dev/pkg/... -v -short -coverprofile profile.cov -coverpkg=gofr.dev/pkg/...
147+
go test gofr.dev/pkg/... -tags migration -v -short -coverprofile packageWithMigration.cov -coverpkg=gofr.dev/pkg/...
148+
grep -v 'gofr.dev/pkg/gofr/migration' packageWithMigration.cov > profile.cov
91149
go tool cover -func profile.cov
92150
93151
- name: Upload Test Coverage
@@ -99,7 +157,7 @@ jobs:
99157
parse_coverage:
100158
name: Code Coverage
101159
runs-on: ubuntu-latest
102-
needs: [Example-Unit-Testing,PKG-Unit-Testing]
160+
needs: [Example-Unit-Testing,PKG-Unit-Testing,MIGRATION-Unit-Testing]
103161
steps:
104162
- name: Check out code into the Go module directory
105163
uses: actions/checkout@v4
@@ -114,6 +172,7 @@ jobs:
114172
run: |
115173
awk '!/^mode: / && FNR==1{print "mode: set"} {print}' ./Example-Test-Report/profile.cov > merged_profile.cov
116174
tail -n +2 ./PKG-Coverage-Report/profile.cov >> merged_profile.cov
175+
tail -n +2 ./MIGRATION-Coverage-Report/profile.cov >> merged_profile.cov
117176
118177
- name: Parse code-coverage value
119178
working-directory: artifacts
@@ -131,7 +190,7 @@ jobs:
131190
upload_coverage:
132191
name: Upload Coverage📊
133192
runs-on: ubuntu-latest
134-
needs: [Example-Unit-Testing,PKG-Unit-Testing]
193+
needs: [Example-Unit-Testing,PKG-Unit-Testing,MIGRATION-Unit-Testing]
135194
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }}
136195
steps:
137196
- name: Check out code into the Go module directory

docs/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ FROM ghcr.io/gofr-dev/website:latest
33
WORKDIR /app
44

55
COPY docs/quick-start /app/src/app/docs/quick-start
6+
COPY docs/public /app/public
67
COPY docs/advanced-guide /app/src/app/docs/advanced-guide
8+
COPY docs/references /app/src/app/docs/references
79
COPY docs/page.md /app/src/app/docs
810
COPY docs/navigation.js /app/src/lib
911

12+
1013
ENV NODE_ENV production
1114

1215
RUN npm install
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Circuit Breaker in HTTP Communication
2+
3+
Calls to remote resources and services can fail due to temporary issues like slow network connections or timeouts, as well as longer-lasting problems such as service unavailability. While transient faults can be mitigated using the "Retry pattern," there are cases where continual retries are futile, such as during severe service failures.
4+
5+
In such scenarios, it's crucial for applications to recognize when an operation is unlikely to succeed and handle the failure appropriately rather than persistently retrying. Indiscriminate use of HTTP retries can even lead to unintentional denial-of-service attacks within the software itself, as multiple clients may flood a failing service with retry attempts.
6+
7+
To prevent this, a defense mechanism like the circuit breaker pattern is essential. Unlike the "Retry pattern" which aims to eventually succeed, the circuit breaker pattern focuses on preventing futile operations. While these patterns can be used together, it's vital for the retry logic to be aware of the circuit breaker's feedback and cease retries if the circuit breaker indicates a non-transient fault.
8+
9+
GoFr inherently provides the functionality, it can be enabled by passing circuit breaker configs as options to `AddHTTPService()` method.
10+
11+
## Usage
12+
13+
```go
14+
package main
15+
16+
import (
17+
"time"
18+
19+
"gofr.dev/pkg/gofr"
20+
"gofr.dev/pkg/gofr/service"
21+
)
22+
23+
func main() {
24+
// Create a new application
25+
app := gofr.New()
26+
27+
app.AddHTTPService("order", "https://order-func",
28+
&service.CircuitBreakerConfig{
29+
// Number of consecutive failed requests after which circuit breaker will be enabled
30+
Threshold: 4,
31+
// Time interval at which circuit breaker will hit the aliveness endpoint.
32+
Interval: 1 * time.Second,
33+
},
34+
)
35+
36+
app.GET("/order", Get)
37+
38+
// Run the application
39+
app.Run()
40+
}
41+
```
42+
43+
Circuit breaker state changes to open when number of consecutive failed requests increases the threshold.
44+
When it is in open state, GoFr makes request to the aliveness endpoint (default being - /.well-known/alive) at an equal interval of time provided in config.
45+
46+
To override the default aliveness endpoint [refer](/docs/advanced-guide/monitoring-service-health)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Custom Spans In Tracing
2+
3+
GoFr's built-in tracing provides valuable insights into your application's behavior. However, sometimes you might need
4+
even more granular details about specific operations within your application. This is where `custom spans` come in.
5+
6+
## How it helps?
7+
By adding custom spans in traces to your requests, you can:
8+
9+
- **Gain granular insights:** Custom spans allow you to track specific operations or functions within your application,
10+
providing detailed performance data.
11+
- **Identify bottlenecks:** By analyzing custom spans, you can pinpoint areas of your code that may be causing
12+
performance bottlenecks or inefficiencies.
13+
- **Improve debugging:** Custom spans enhance your ability to debug issues by providing visibility into the execution
14+
flow of your application.
15+
16+
## Usage
17+
18+
To add a custom trace to a request, you can use the `Trace()` method of GoFr context, which takes the name of the span as an argument
19+
and returns a trace.Span.
20+
21+
```go
22+
func MyHandler(c context.Context) error {
23+
span := c.Trace("my-custom-span")
24+
defer span.Close()
25+
26+
// Do some work here
27+
return nil
28+
}
29+
```
30+
31+
In this example, **my-custom-span** is the name of the custom span that you want to add to the request.
32+
The defer statement ensures that the span is closed even if an error occurs to ensure that the trace is properly recorded.
33+
34+
35+

docs/advanced-guide/handling-data-migrations/page.md

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,22 @@
11
# Handling Data Migrations
22

3-
Gofr supports data migrations for MySQL and Redis which allows to alter the state of a database, be it adding a new column to existing table or modifying the data type of an existing column or adding constraints to an existing table, setting and removing keys etc.
4-
5-
**How Migrations help?**
6-
7-
Suppose you manually edit fragments of your database, and now it's your responsibility to inform other developers to execute them. Additionally, you need to keep track of which changes should be applied to production machines in the next deployment.
8-
9-
GoFr maintains the table called **gofr_migration** which helps in such case. This table tracks which migrations have already been executed and ensures that only migrations that have never been run are executed. This way, you only need to ensure that your migrations are properly in place. ([Learn more](https://cloud.google.com/architecture/database-migration-concepts-principles-part-1))
3+
Suppose you manually make changes to your database, and now it's your responsibility to inform other developers to execute them. Additionally, you need to keep track of which changes should be applied to production machines in the next deployment.
4+
Gofr supports data migrations for MySQL, Postgres and Redis which allows to alter the state of a database, be it adding a new column to existing table or modifying the data type of existing column or adding constraints to an existing table, setting and removing keys etc.
105

116
## Usage
127

13-
We will create an employee table using migrations.
14-
158
### Creating Migration Files
169

1710
It is recommended to maintain a migrations directory in your project root to enhance readability and maintainability.
1811

1912
**Migration file names**
2013

21-
It is recommended that each migration file should be numbered using the unix timestamp when the migration was created, This helps prevent numbering conflicts when working in a team environment.
14+
It is recommended that each migration file should be numbered in the format of *YYYYMMDDHHMMSS* when the migration was created.
15+
This helps prevent numbering conflicts and allows for maintaining the correct sort order by name in different filesystem views.
2216

2317
Create the following file in migrations directory.
2418

25-
**Filename : 1708322067_create_employee_table.go**
19+
**Filename : 20240226153000_create_employee_table.go**
2620
```go
2721
package migrations
2822

@@ -41,7 +35,7 @@ const createTable = `CREATE TABLE IF NOT EXISTS employee
4135
func createTableEmployee() migration.Migrate {
4236
return migration.Migrate{
4337
UP: func(d migration.Datasource) error {
44-
_, err := d.DB.Exec(createTable)
38+
_, err := d.SQL.Exec(createTable)
4539
if err != nil {
4640
return err
4741
}
@@ -51,10 +45,10 @@ func createTableEmployee() migration.Migrate {
5145
}
5246
```
5347

54-
`migration.Datasource` have the datasources whose migrations are supported which are Redis and MySQL.
55-
All the migrations run in transactions by default.
48+
`migration.Datasource` have the datasources whose migrations are supported i.e. Redis and SQL (MySQL and PostgreSQL).
49+
All the migrations always run in a transaction.
5650

57-
For MySQL it is highly recommended to use `IF EXISTS` and `IF NOT EXIST` in DDL commands as MySQL implicitly commits these Commands.
51+
For MySQL it is highly recommended to use `IF EXISTS` and `IF NOT EXIST` in DDL commands as MySQL implicitly commits these commands.
5852

5953
**Create a function which returns all the migrations in a map**
6054

@@ -66,7 +60,7 @@ import "gofr.dev/pkg/gofr/migration"
6660

6761
func All() map[int64]migration.Migrate {
6862
return map[int64]migration.Migrate{
69-
1708322067: createTableEmployee(),
63+
20240226153000: createTableEmployee(),
7064
}
7165
}
7266
```
@@ -78,9 +72,6 @@ Migrations will run in ascending order of keys in this map.
7872
package main
7973

8074
import (
81-
"errors"
82-
"fmt"
83-
8475
"gofr.dev/examples/using-migrations/migrations"
8576
"gofr.dev/pkg/gofr"
8677
)
@@ -101,9 +92,56 @@ func main() {
10192
When we run the app we will see the following logs for migrations which ran successfully.
10293

10394
```bash
104-
INFO [16:55:46] Migration 1708322067 ran successfully
95+
INFO [16:55:46] Migration 20240226153000 ran successfully
10596
```
10697

10798

10899

109100

101+
GoFr maintains the records in the database itself which helps in tracking which migrations have already been executed and ensures that only migrations that have never been run are executed.
102+
This way, you only need to ensure that your migrations are properly in place. ([Learn more](https://cloud.google.com/architecture/database-migration-concepts-principles-part-1))
103+
104+
## Migration Records
105+
106+
**SQL**
107+
108+
Migration records are stored and maintained in **gofr_migrations** table which has the following schema:
109+
110+
{% table %}
111+
* Field
112+
* Type
113+
---
114+
* version
115+
* bigint
116+
---
117+
* method
118+
* varchar(4)
119+
---
120+
* start_time
121+
* timestamp
122+
---
123+
* duration
124+
* bigint
125+
---
126+
{% /table %}
127+
128+
**REDIS**
129+
130+
Migration records are stored and maintained in a Redis Hash named **gofr_migrations** where key is the version and value contains other details in JSON format.
131+
132+
Example :
133+
134+
Key : 20240226153000
135+
136+
Value : {"method":"UP","startTime":"2024-02-26T15:03:46.844558+05:30","duration":0}
137+
138+
Where,
139+
140+
**Version** : Migration version is the number provided in the map, i.e. sequence number.
141+
142+
**Start Time** : Time when Migration Started in UTC.
143+
144+
**Duration** : Time taken by Migration since it started in milliseconds.
145+
146+
**Method** : It contains the method(UP/DOWN) in which migration ran.
147+
(For now only method UP is supported)

0 commit comments

Comments
 (0)