Skip to content

Commit 2d2c3b4

Browse files
committed
feat: duplicate functions for API request to make it possible using the CNJ code search using the pagination feature. Not the best solution, but it will work
1 parent d8270b3 commit 2d2c3b4

File tree

2 files changed

+242
-0
lines changed

2 files changed

+242
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package request
2+
3+
import (
4+
"github.com/DanielFillol/DataJUD_API_CALLER/models"
5+
"log"
6+
"sync"
7+
)
8+
9+
// AsyncAPIRequestCode makes API requests asynchronously
10+
func AsyncAPIRequestCode(users []models.ReadCsvCode, numberOfWorkers int, url string, method string, auth string) ([]models.ResponseBodyNextPage, error) {
11+
// Create a channel to signal when the goroutines are done processing inputs
12+
done := make(chan struct{})
13+
defer close(done)
14+
// Create a channel to receive inputs from
15+
inputCh := StreamInputsCode(done, users)
16+
17+
// Create a wait group to wait for the worker goroutines to finish
18+
var wg sync.WaitGroup
19+
wg.Add(numberOfWorkers)
20+
21+
// Create a channel to receive results from
22+
resultCh := make(chan models.ResponseBodyNextPage)
23+
24+
// Spawn worker goroutines to process inputs
25+
var errorOnApiRequests error
26+
for i := 0; i < numberOfWorkers; i++ {
27+
go func() {
28+
// Each worker goroutine consumes inputs from the shared input channel
29+
for input := range inputCh {
30+
// Make the API request and send the response to the result channel
31+
bodyStr, err := APIRequestCode(url+input.CourtName+API, method, auth, input)
32+
resultCh <- bodyStr
33+
if err != nil {
34+
// If there is an error making the API request, print the error
35+
log.Println("error send request: " + err.Error())
36+
errorOnApiRequests = err
37+
//break
38+
}
39+
log.Println("success send request: " + "200 " + input.CourtName)
40+
}
41+
// When the worker goroutine is done processing inputs, signal the wait group
42+
wg.Done()
43+
}()
44+
}
45+
46+
// Wait for all worker goroutines to finish processing inputs
47+
go func() {
48+
wg.Wait()
49+
close(resultCh)
50+
}()
51+
52+
// Return early on error in any given call on API requests
53+
if errorOnApiRequests != nil {
54+
return nil, errorOnApiRequests
55+
}
56+
57+
// Collect results from the result channel and return them as a slice
58+
var results []models.ResponseBodyNextPage
59+
for result := range resultCh {
60+
results = append(results, result)
61+
}
62+
63+
return results, nil
64+
}
65+
66+
// StreamInputsCode sends inputs from a slice to a channel
67+
func StreamInputsCode(done <-chan struct{}, inputs []models.ReadCsvCode) <-chan models.ReadCsvCode {
68+
// Create a channel to send inputs to
69+
inputCh := make(chan models.ReadCsvCode)
70+
go func() {
71+
defer close(inputCh)
72+
for _, input := range inputs {
73+
select {
74+
case inputCh <- input:
75+
case <-done:
76+
// If the done channel is closed prematurely, finish the loop (closing the input channel)
77+
break
78+
}
79+
}
80+
}()
81+
return inputCh
82+
}

request/api_request_codeSearch.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package request
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"errors"
7+
"github.com/DanielFillol/DataJUD_API_CALLER/models"
8+
"io/ioutil"
9+
"log"
10+
"strconv"
11+
)
12+
13+
// APIRequestCode makes an API request to the specified URL using the specified HTTP method and authentication header.
14+
// It returns a models.ResponseBodyNextPage struct containing the API response body and an error (if any).
15+
func APIRequestCode(url, method string, auth string, request models.ReadCsvCode) (models.ResponseBodyNextPage, error) {
16+
// Create responseReturn new BodyRequestLawsuit struct with the document ID and pagination settings for the initial API call.
17+
class, err := strconv.Atoi(request.ClassCode)
18+
if err != nil {
19+
return models.ResponseBodyNextPage{}, errors.New("failed to parse the class code to int: " + request.ClassCode)
20+
}
21+
court, err := strconv.Atoi(request.CourtCode)
22+
if err != nil {
23+
return models.ResponseBodyNextPage{}, errors.New("failed to parse the court code to int: " + request.CourtCode)
24+
}
25+
26+
req := models.BodyRequestCode{
27+
Size: 100,
28+
Query: models.Query{
29+
Bool: models.Bool{
30+
Must: []models.Must{
31+
{Match: models.Match{ClasseCodigo: class}},
32+
{Match: models.Match{OrgaoJulgadorCodigo: court}},
33+
},
34+
},
35+
},
36+
Sort: []models.Sort{{models.Timestamp{Order: "asc"}}},
37+
}
38+
39+
// Serialize the BodyRequestLawsuit struct to JSON.
40+
jsonReq, err := json.Marshal(req)
41+
if err != nil {
42+
return models.ResponseBodyNextPage{}, errors.New(err.Error())
43+
}
44+
45+
// Create responseReturn new buffer with the JSON-encoded request body.
46+
reqBody := bytes.NewBuffer(jsonReq)
47+
48+
// Make the API call and get the response.
49+
res, err := call(url, method, auth, reqBody)
50+
if err != nil {
51+
return models.ResponseBodyNextPage{}, errors.New(err.Error())
52+
}
53+
54+
// Read the response body.
55+
body, err := ioutil.ReadAll(res.Body)
56+
if err != nil {
57+
return models.ResponseBodyNextPage{}, errors.New(err.Error())
58+
}
59+
60+
// Unmarshal the response body into responseReturn ResponseBodyLawsuit struct.
61+
var response models.ResponseBodyNextPage
62+
err = json.Unmarshal(body, &response)
63+
if err != nil {
64+
return models.ResponseBodyNextPage{}, errors.New(err.Error())
65+
}
66+
67+
responseReturn := models.ResponseBodyNextPage{
68+
Took: response.Took,
69+
TimedOut: response.TimedOut,
70+
Shards: response.Shards,
71+
Hit: response.Hit,
72+
}
73+
74+
// If the API response has more pages of data, make additional API calls and append the results to the response.
75+
if len(response.Hit.Hits) == 100 {
76+
nextPage := strconv.Itoa(int(response.Hit.Hits[99].Sort[0]))
77+
// Make the API call and get the response.
78+
lawsuits, err := callNextPage(url, method, auth, req, nextPage)
79+
if err != nil {
80+
return models.ResponseBodyNextPage{}, errors.New(err.Error())
81+
}
82+
83+
responseReturn.Hit.Hits = append(responseReturn.Hit.Hits, lawsuits...)
84+
return responseReturn, nil
85+
}
86+
87+
return responseReturn, nil
88+
}
89+
90+
// callNextPage returns a slice of models.Lawsuit structs containing the data from all pages of the API response.
91+
func callNextPage(url string, method string, auth string, req models.BodyRequestCode, cursor string) ([]models.Hit2NextPage, error) {
92+
var lawsuits []models.Hit2NextPage
93+
c, err := strconv.Atoi(cursor)
94+
if err != nil {
95+
return lawsuits, errors.New("could not covert cursor into int: " + cursor)
96+
}
97+
98+
for {
99+
log.Println("success getting next page:" + strconv.Itoa(c))
100+
// Create a new BodyRequest struct with the document ID and updated pagination settings for the next API call.
101+
request := models.BodyRequestCodeNextPage{
102+
Size: 100,
103+
Query: models.Query{
104+
Bool: models.Bool{
105+
Must: []models.Must{
106+
{Match: models.Match{ClasseCodigo: req.Query.Bool.Must[0].Match.ClasseCodigo}},
107+
{Match: models.Match{OrgaoJulgadorCodigo: req.Query.Bool.Must[1].Match.OrgaoJulgadorCodigo}},
108+
},
109+
},
110+
},
111+
Sort: []models.Sort{{models.Timestamp{Order: "asc"}}},
112+
SearchAfter: []int64{int64(c)},
113+
}
114+
115+
// Serialize the BodyRequest struct to JSON.
116+
jsonReq, err := json.Marshal(request)
117+
if err != nil {
118+
log.Println(err)
119+
return lawsuits, err
120+
}
121+
122+
// Create a new buffer with the JSON-encoded request body.
123+
reqBody := bytes.NewBuffer(jsonReq)
124+
125+
// Call the API using the provided url, method, authorization, and request body.
126+
res, err := call(url, method, auth, reqBody)
127+
if err != nil {
128+
log.Println(err)
129+
return lawsuits, errors.New(err.Error())
130+
}
131+
132+
// Read the response body.
133+
body, err := ioutil.ReadAll(res.Body)
134+
if err != nil {
135+
log.Println(err)
136+
return lawsuits, err
137+
}
138+
139+
// Unmarshal the response body into a models.ResponseBody struct.
140+
var response models.ResponseBodyNextPage
141+
err = json.Unmarshal(body, &response)
142+
if err != nil {
143+
log.Println(err)
144+
return lawsuits, err
145+
}
146+
147+
// Append the current response to the lawsuits slice.
148+
lawsuits = append(lawsuits, response.Hit.Hits...)
149+
150+
// If the API response indicates there are no more pages, break out of the loop.
151+
if len(response.Hit.Hits) < 100 {
152+
break
153+
}
154+
155+
// Update the cursor for the next API call.
156+
c = int(response.Hit.Hits[99].Sort[0])
157+
}
158+
159+
return lawsuits, nil
160+
}

0 commit comments

Comments
 (0)