Skip to content

Commit 3d8aeb2

Browse files
authored
chore: make less calls to api endpoints (#163)
1 parent 64435ed commit 3d8aeb2

14 files changed

Lines changed: 202 additions & 123 deletions

.github/workflows/pull-data.yaml

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,11 @@ jobs:
9696
name: Pull data
9797
if: env.stale == 'true'
9898
run: |
99-
jq -rc '.[]' configuration.json | while read CONFIG; do
100-
ZONE=$(echo "$CONFIG" | jq -r '.zone')
101-
FROM=$(echo "$CONFIG" | jq -r '.latest')
102-
END=$(echo "$CONFIG" | jq -r '.end')
103-
104-
echo "Pull data for ${ZONE} until ${END}..."
105-
go run download.go --zone ${ZONE} --from ${FROM} --end ${END} --output ./github-pages/api/energy-price/ --limit 0 --v2date 1758326400
106-
echo "changed=true" >> $GITHUB_ENV
107-
done
99+
FROM=$(jq -r 'map(.latest) | min' configuration.json)
100+
END=$(jq -r 'map(.end) | max' configuration.json)
101+
ZONES=$(jq -r '[.[].zone] | join(",")' configuration.json)
102+
go run download.go --zones ${ZONES} --from ${FROM} --end ${END} --output ./github-pages/api/energy-price/ --limit 0 --v2date 1758326400
103+
echo "changed=true" >> $GITHUB_ENV
108104
109105
- shell: bash
110106
name: Index data
@@ -208,25 +204,20 @@ jobs:
208204
name: Pull data
209205
if: env.stale == 'true'
210206
run: |
211-
jq -rc '.[]' configuration.json | while read CONFIG; do
212-
ZONE=$(echo "$CONFIG" | jq -r '.zone')
213-
FROM=$(echo "$CONFIG" | jq -r '.latest')
214-
END=$(echo "$CONFIG" | jq -r '.end')
215-
216-
echo "Pull data for ${ZONE} until ${END}..."
217-
sh src/renewables-data-pull.sh $ZONE $FROM $END > "${ZONE}.generated"
218-
echo "changed=true" >> $GITHUB_ENV
219-
done
207+
FROM=$(jq -r 'map(.latest) | min' configuration.json)
208+
END=$(jq -r 'map(.end) | max' configuration.json)
209+
sh src/renewables-data-pull.sh $FROM $END > fetched-data
210+
echo "changed=true" >> $GITHUB_ENV
220211
221212
- shell: bash
222213
name: Write data
223214
if: env.changed == 'true'
224215
run: |
225-
for GENERATED in *.generated; do
226-
[ -f "$GENERATED" ] || continue
227-
ZONE=$(basename $GENERATED .generated)
216+
jq -rc '.[]' configuration.json | while read CONFIG; do
217+
ZONE=$(echo "$CONFIG" | jq -r '.zone')
228218
echo "Using generated data for ${ZONE}..."
229-
sh src/data-write.sh $GENERATED ./github-pages/api/renewables/ $ZONE
219+
jq -c "map(select(.zone == \"$ZONE\") | del(.zone))" fetched-data > "${ZONE}.generated"
220+
sh src/data-write.sh "${ZONE}.generated" ./github-pages/api/renewables/ $ZONE
230221
done
231222
232223
- shell: bash
@@ -329,25 +320,20 @@ jobs:
329320
name: Pull data
330321
if: env.stale == 'true'
331322
run: |
332-
jq -rc '.[]' configuration.json | while read CONFIG; do
333-
ZONE=$(echo "$CONFIG" | jq -r '.zone')
334-
FROM=$(echo "$CONFIG" | jq -r '.latest')
335-
END=$(echo "$CONFIG" | jq -r '.end')
336-
337-
echo "Pull data for ${ZONE} until ${END}..."
338-
sh src/co2-emission-data-pull.sh $ZONE $FROM $END > "${ZONE}.generated"
339-
echo "changed=true" >> $GITHUB_ENV
340-
done
323+
FROM=$(jq -r 'map(.latest) | min' configuration.json)
324+
END=$(jq -r 'map(.end) | max' configuration.json)
325+
sh src/co2-emission-data-pull.sh $FROM $END > fetched-data
326+
echo "changed=true" >> $GITHUB_ENV
341327
342328
- shell: bash
343329
name: Write data
344330
if: env.changed == 'true'
345331
run: |
346-
for GENERATED in *.generated; do
347-
[ -f "$GENERATED" ] || continue
348-
ZONE=$(basename $GENERATED .generated)
332+
jq -rc '.[]' configuration.json | while read CONFIG; do
333+
ZONE=$(echo "$CONFIG" | jq -r '.zone')
349334
echo "Using generated data for ${ZONE}..."
350-
sh src/data-write.sh $GENERATED ./github-pages/api/emission/co2/ $ZONE
335+
jq -c "map(select(.zone == \"$ZONE\") | del(.zone))" fetched-data > "${ZONE}.generated"
336+
sh src/data-write.sh "${ZONE}.generated" ./github-pages/api/emission/co2/ $ZONE
351337
done
352338
353339
- shell: bash

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ _test-json:
3535
@find .vscode configuration test/fixtures testdata -type f -iname '*.json*' -print0 | xargs -0 -I {} echo 'echo Checking: {}; jq empty < {}' | sort | sh -e
3636

3737
test-makefile:
38-
$(COMPOSE_RUN) makelint
38+
test -z "$$(make -n all 1>/dev/null)"
3939

4040
test-markdown:
4141
$(COMPOSE_RUN) markdownlint --disable MD013 MD031 MD032 -- README.md documentation/*.md

compose.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ services:
2727
volumes:
2828
- .:/workspace:ro
2929
working_dir: /workspace
30-
makelint:
31-
image: mrtazz/checkmake
32-
volumes:
33-
- ./Makefile:/Makefile:ro
3430
markdownlint:
3531
image: ghcr.io/igorshubovych/markdownlint-cli
3632
volumes:

download.go

Lines changed: 64 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"path/filepath"
1414
"sort"
1515
"strconv"
16+
"strings"
1617
"time"
1718
)
1819

@@ -29,8 +30,9 @@ var (
2930

3031
func main() {
3132
conf := NewConfiguration()
33+
zones := ""
3234

33-
flag.StringVar(&conf.Zone, "zone", conf.Zone, "Price Area like DK1")
35+
flag.StringVar(&zones, "zones", zones, "Comma-separated list of price areas to keep")
3436
flag.StringVar(&conf.Output, "output", conf.Output, "Directory to place output into")
3537
flag.StringVar(&conf.Endpoint, "endpoint", conf.Endpoint, "Endpoint to fetch from")
3638
flag.Int64Var(&conf.V2Date, "v2date", conf.V2Date, "Date when day-a-head prices take effect")
@@ -40,6 +42,11 @@ func main() {
4042
flag.IntVar(&conf.SleepInterval, "sleep-interval", conf.SleepInterval, "Milliseconds to sleep when API is throttling")
4143

4244
flag.Parse()
45+
46+
if zones != "" {
47+
conf.Zones = strings.Split(zones, ",")
48+
}
49+
4350
err := conf.Validate()
4451
if err != nil {
4552
log.Fatal(err)
@@ -62,31 +69,52 @@ func run(c Configuration) error {
6269

6370
func runConfigurations(cs []Configuration) error {
6471
for _, c := range cs {
65-
records, err := fetchRecords(c.Endpoint, c.Zone, c.From, c.End, c.Limit, c.SleepInterval, c.apiVersion)
72+
records, err := fetchRecords(c.Endpoint, c.From, c.End, c.Limit, c.SleepInterval, c.apiVersion)
6673
if err != nil {
6774
return err
6875
}
6976

70-
err = saveRecords(c.Zone, records, c.Output, c.apiVersion)
77+
err = saveRecords(records, c.Zones, c.Output, c.apiVersion)
7178
if err != nil {
7279
return err
7380
}
7481
}
7582
return nil
7683
}
7784

78-
func saveRecords(zone string, records []Record, output string, version ApiVersion) error {
85+
func saveRecords(records []Record, zones []string, output string, version ApiVersion) error {
86+
byZone := make(map[string][]Record)
87+
for _, r := range records {
88+
byZone[r.Zone] = append(byZone[r.Zone], r)
89+
}
90+
91+
zoneSet := make(map[string]bool)
92+
for _, z := range zones {
93+
zoneSet[z] = true
94+
}
95+
7996
outputs := make(map[string][]Record)
8097

81-
switch version {
82-
case ApiV2:
83-
for file, value := range produceOutputs(records, filepath.Join(output, "v2"), 15*time.Minute, filepath.Join(zone, "index.json")) {
84-
outputs[file] = append(outputs[file], value...)
98+
for zone, zoneRecords := range byZone {
99+
if !zoneSet[zone] {
100+
continue
85101
}
86-
fallthrough
87-
case ApiV1:
88-
for file, value := range produceOutputs(records, output, 1*time.Hour, fmt.Sprintf("%s.json", zone)) {
89-
outputs[file] = append(outputs[file], value...)
102+
103+
stripped := make([]Record, len(zoneRecords))
104+
for i, r := range zoneRecords {
105+
stripped[i] = Record{Euro: r.Euro, Timestamp: r.Timestamp}
106+
}
107+
108+
switch version {
109+
case ApiV2:
110+
for file, value := range produceOutputs(stripped, filepath.Join(output, "v2"), 15*time.Minute, filepath.Join(zone, "index.json")) {
111+
outputs[file] = append(outputs[file], value...)
112+
}
113+
fallthrough
114+
case ApiV1:
115+
for file, value := range produceOutputs(stripped, output, 1*time.Hour, fmt.Sprintf("%s.json", zone)) {
116+
outputs[file] = append(outputs[file], value...)
117+
}
90118
}
91119
}
92120

@@ -205,21 +233,21 @@ func updateOutput(file string, records []Record) ([]Record, error) {
205233
return updated, nil
206234
}
207235

208-
func fetchRecords(endpoint string, zone string, from int64, end int64, limit int, sleep int, version ApiVersion) ([]Record, error) {
236+
func fetchRecords(endpoint string, from int64, end int64, limit int, sleep int, version ApiVersion) ([]Record, error) {
209237
var (
210-
data = make(map[int64]Record)
238+
data = make(map[recordKey]Record)
211239
records = make([]Record, 0)
212240
req string
213241
bytes []byte
214242
err error
215243
items []Record
216244
item Record
217245
size int
218-
key int64
246+
key recordKey
219247
)
220248

221249
for from < end {
222-
req, err = buildRequest(endpoint, zone, from, end, limit, version)
250+
req, err = buildRequest(endpoint, from, end, limit, version)
223251
if err != nil {
224252
return records, err
225253
}
@@ -236,16 +264,16 @@ func fetchRecords(endpoint string, zone string, from int64, end int64, limit int
236264

237265
size = len(data)
238266
for _, item = range items {
239-
data[item.Timestamp] = item
267+
data[recordKey{timestamp: item.Timestamp, zone: item.Zone}] = item
240268
}
241269

242270
if len(data) == size {
243271
break
244272
}
245273

246274
for key = range data {
247-
if key > from {
248-
from = key
275+
if key.timestamp > from {
276+
from = key.timestamp
249277
}
250278
}
251279

@@ -261,7 +289,7 @@ func fetchRecords(endpoint string, zone string, from int64, end int64, limit int
261289
return records, nil
262290
}
263291

264-
func buildRequest(endpoint string, zone string, from int64, end int64, limit int, version ApiVersion) (string, error) {
292+
func buildRequest(endpoint string, from int64, end int64, limit int, version ApiVersion) (string, error) {
265293
var (
266294
params = url.Values{}
267295
uri *url.URL
@@ -285,7 +313,6 @@ func buildRequest(endpoint string, zone string, from int64, end int64, limit int
285313
}
286314

287315
params.Add("end", time.Unix(end, 0).Format("2006-01-02T15:04"))
288-
params.Add("filter", fmt.Sprintf(`{"PriceArea":"%s"}`, zone))
289316
params.Add("limit", strconv.Itoa(limit))
290317
params.Add("start", time.Unix(from, 0).Format("2006-01-02T15:04"))
291318
params.Add("timezone", "UTC")
@@ -360,7 +387,7 @@ func parseBodyV1(body []byte) ([]Record, error) {
360387
if err != nil {
361388
return records, errors.Join(errConvert, err)
362389
}
363-
records = append(records, Record{Euro: item.Euro, Timestamp: stamp.Unix()})
390+
records = append(records, Record{Euro: item.Euro, Timestamp: stamp.Unix(), Zone: item.Zone})
364391
}
365392

366393
return records, nil
@@ -384,7 +411,7 @@ func parseBodyV2(body []byte) ([]Record, error) {
384411
if err != nil {
385412
return records, errors.Join(errConvert, err)
386413
}
387-
records = append(records, Record{Euro: item.Euro, Timestamp: stamp.Unix()})
414+
records = append(records, Record{Euro: item.Euro, Timestamp: stamp.Unix(), Zone: item.Zone})
388415
}
389416

390417
return records, nil
@@ -398,10 +425,11 @@ const (
398425
)
399426

400427
type Configuration struct {
401-
Zone, Output, Endpoint string
402-
From, End, V2Date int64
403-
Limit, SleepInterval int
404-
apiVersion ApiVersion
428+
Output, Endpoint string
429+
Zones []string
430+
From, End, V2Date int64
431+
Limit, SleepInterval int
432+
apiVersion ApiVersion
405433
}
406434

407435
func NewConfiguration() Configuration {
@@ -414,7 +442,7 @@ func NewConfiguration() Configuration {
414442
}
415443

416444
func (f *Configuration) Validate() error {
417-
if len(f.Zone) == 0 || len(f.Output) == 0 || f.From == 0 || f.End == 0 {
445+
if len(f.Zones) == 0 || len(f.Output) == 0 || f.From == 0 || f.End == 0 {
418446
return fmt.Errorf("missing flag, provided flags: %s", os.Args[1:])
419447
}
420448

@@ -455,9 +483,15 @@ func (c *Configuration) Partitions() ([]Configuration, error) {
455483
return parts, nil
456484
}
457485

486+
type recordKey struct {
487+
timestamp int64
488+
zone string
489+
}
490+
458491
type Record struct {
459492
Euro float32 `json:"euro"`
460493
Timestamp int64 `json:"timestamp"`
494+
Zone string `json:"zone,omitempty"`
461495
}
462496

463497
type SpotRecords struct {
@@ -467,6 +501,7 @@ type SpotRecords struct {
467501
type SpotRecord struct {
468502
Euro float32 `json:"SpotPriceEUR"`
469503
Timestamp string `json:"HourUTC"`
504+
Zone string `json:"PriceArea"`
470505
}
471506

472507
type DayAHeadRecords struct {
@@ -476,4 +511,5 @@ type DayAHeadRecords struct {
476511
type DayAHeadRecord struct {
477512
Euro float32 `json:"DayAheadPriceEUR"`
478513
Timestamp string `json:"TimeUTC"`
514+
Zone string `json:"PriceArea"`
479515
}

0 commit comments

Comments
 (0)