Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exp/services/ledgerexporter: Initial draft #5160

Merged
merged 78 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
bc44ebd
Ledgerexporter xdr changes
urvisavla Jan 9, 2024
28ca57a
Rewrite ledgerexporter using new xdr
urvisavla Jan 9, 2024
a6f9d99
Add basic test
urvisavla Jan 9, 2024
9aed8dc
Fixes
urvisavla Jan 10, 2024
a66a24f
Start upload in a separate go routine
urvisavla Jan 10, 2024
2822040
Naming changes and other refactoring
urvisavla Jan 11, 2024
19a5bad
Add condition to prevent file overwrite for GCS
urvisavla Jan 12, 2024
836661f
Adjust range based on ledgersperfile config parameter
urvisavla Jan 12, 2024
06015f7
Improve handling of ledger range and added a unit test.
urvisavla Jan 12, 2024
e8b4859
Update comments
urvisavla Jan 12, 2024
0eedb07
Added error handling and addressing review comments
urvisavla Jan 16, 2024
4ede9e2
Minor changes
urvisavla Jan 16, 2024
a113d5b
Update exp/services/ledgerexporter/exportmanager.go
urvisavla Jan 17, 2024
a6341fa
Update exp/services/ledgerexporter/exportmanager.go
urvisavla Jan 17, 2024
9ad4746
Update exp/services/ledgerexporter/uploader.go
urvisavla Jan 17, 2024
3f8a83b
Addressing review comments
urvisavla Jan 18, 2024
a8b403a
Improved code organization.
urvisavla Jan 18, 2024
509861e
Add README.md
urvisavla Jan 18, 2024
b87fce6
Improve validations and error handling
urvisavla Jan 18, 2024
5fb16d9
Add unit tests for ledger range adjustments based on config and fix a…
urvisavla Jan 18, 2024
d00cbd7
Removing redundant data from the LedgerCloseMetaObject. Adding checks…
urvisavla Jan 19, 2024
2b1106c
Fix static check error
urvisavla Jan 19, 2024
9d4a5b6
Disable ledgerexporter job from github workflow
urvisavla Jan 19, 2024
888ab26
Fix linter errors
urvisavla Jan 19, 2024
84e4245
Remove conditional puts for now to avoid potential disruption for exi…
urvisavla Jan 19, 2024
d7eddbe
fix ci error
urvisavla Jan 19, 2024
e24fa9b
Disable ledger-exporter job from ci
urvisavla Jan 24, 2024
a18b14a
update logging
urvisavla Jan 24, 2024
e88d565
Exportmanager code refactoring
urvisavla Jan 25, 2024
397d881
Add gzip compression
urvisavla Jan 25, 2024
4938e89
Add start-from-last-n-ledger option
urvisavla Jan 25, 2024
3fb9f07
refactoring export object
urvisavla Jan 30, 2024
90f7cef
Add conditional uploads
urvisavla Jan 30, 2024
166c4cc
Validate supplied ledge range and add unit tests
urvisavla Jan 30, 2024
946a673
Update README
urvisavla Jan 30, 2024
85675bc
Update exp/services/ledgerexporter/internal/app.go
urvisavla Jan 30, 2024
3f73670
Update exp/services/ledgerexporter/internal/datastore.go
urvisavla Jan 30, 2024
4df4989
Addressing review comments
urvisavla Feb 1, 2024
f352552
Add unit test coverage for the Uploader
urvisavla Feb 1, 2024
e923c13
Generate default captive-core config based on the specified 'network'
urvisavla Feb 1, 2024
f592361
Files missed in previous commit
urvisavla Feb 1, 2024
e380b5c
Add default testnet and pubnet configs for captive-core
urvisavla Feb 1, 2024
a66e11b
Fix ci errors
urvisavla Feb 1, 2024
a51e959
Update cloud.google.com/go/storage package to latest
urvisavla Feb 1, 2024
e648557
Use idiomatic go receiver pattern for config
urvisavla Feb 8, 2024
c566989
Remove captive_core_use_db config param.
urvisavla Feb 8, 2024
5d847fb
Set useragent
urvisavla Feb 8, 2024
e51467d
Set captive-core on-disk mode by default
urvisavla Feb 8, 2024
1ffb57e
Update exp/services/ledgerexporter/README.md
urvisavla Feb 8, 2024
49b7ce1
The captive-core config section is omitted as it's automatically deri…
urvisavla Feb 13, 2024
7ad8ada
Update exp/services/ledgerexporter/internal/app.go
urvisavla Feb 13, 2024
46655b8
Fix unittests
urvisavla Feb 13, 2024
c531e76
Addressing review comment
urvisavla Feb 13, 2024
97bc1a0
Addressing review comments
urvisavla Feb 13, 2024
4d39d2d
Remove doneCh
urvisavla Feb 14, 2024
69480ab
Pass app context to the datastore
urvisavla Feb 14, 2024
ead1bde
Resolve merge conflict
urvisavla Feb 20, 2024
42e2545
Regenerate xdr after Makefile update
urvisavla Feb 20, 2024
83f0429
Add XDRGzipEncoder and XDRGzipDecoder
urvisavla Feb 20, 2024
ca1c285
Addressing review comments
urvisavla Feb 20, 2024
977bb53
Addressing review comments
urvisavla Feb 21, 2024
24d2fad
Move captive-core default configs to ledgerbackend package.
urvisavla Feb 21, 2024
c02f09a
Addressing review comment
urvisavla Feb 21, 2024
a68d9b2
Update exp/services/ledgerexporter/internal/utils.go
urvisavla Feb 21, 2024
d2ba02d
Update exp/services/ledgerexporter/internal/utils.go
urvisavla Feb 21, 2024
03a6dbb
removed unused code and other minor changes
urvisavla Feb 21, 2024
2a97dc5
Addressing review comments
urvisavla Feb 21, 2024
9ed7ee2
Do not store ctx in App struct
urvisavla Feb 21, 2024
59093c8
Handle canceled context in AddLedgerCloseMeta
urvisavla Feb 22, 2024
8d91ef3
Improved uploader shutdown logic
urvisavla Feb 22, 2024
ec4283b
Address review comments
urvisavla Feb 22, 2024
44eb740
Export manager holds only a single current meta archive
urvisavla Feb 22, 2024
ba15276
Update exp/services/ledgerexporter/internal/uploader.go
urvisavla Feb 22, 2024
1bf8c45
Address review comments
urvisavla Feb 22, 2024
bea88e5
Update exp/services/ledgerexporter/internal/config.go
urvisavla Feb 24, 2024
92b7392
Misc. minor improvements
urvisavla Feb 26, 2024
717c3dc
Use replace instead of assert in unit tests
urvisavla Feb 27, 2024
cbb3a5b
Update README
urvisavla Feb 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/horizon.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ jobs:
ledger-exporter:
name: Test and push the Ledger Exporter images
runs-on: ubuntu-latest
if: false # Disable the job
steps:
- uses: actions/checkout@v3
with:
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ xdr/Stellar-contract.x \
xdr/Stellar-internal.x \
xdr/Stellar-contract-config-setting.x

XDRS = $(DOWNLOADABLE_XDRS) xdr/Stellar-lighthorizon.x

XDRS = $(DOWNLOADABLE_XDRS) xdr/Stellar-lighthorizon.x \
xdr/Stellar-exporter.x


XDRGEN_COMMIT=e2cac557162d99b12ae73b846cf3d5bfe16636de
Expand Down
80 changes: 80 additions & 0 deletions exp/services/ledgerexporter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Ledger Exporter (Work in Progress)

The Ledger Exporter is a tool designed to export ledger data from a Stellar network and upload it to a specified destination. It supports both bounded and unbounded modes, allowing users to export a specific range of ledgers or continuously export new ledgers as they arrive on the network.

Ledger Exporter currently uses captive-core as the ledger backend and GCS as the destination data store.

# Exported Data Format
The tool allows for the export of multiple ledgers in a single exported file. The exported data is in XDR format and is compressed (gzip) before being uploaded.

```go
type LedgerCloseMetaBatch struct {
StartSequence uint32
EndSequence uint32
LedgerCloseMetas []LedgerCloseMeta
}
```

## Getting Started

### Installation (coming soon)

### Command Line Options

#### Bounded Mode:
Exports a specific range of ledgers, defined by --start and --end.
```bash
ledgerexporter --start <start_ledger> --end <end_ledger> --config-file <config_file_path>
urvisavla marked this conversation as resolved.
Show resolved Hide resolved
```

#### Unbounded Mode:
Exports ledgers continuously starting from --start. In this mode, the end ledger is either not provided or set to 0.
```bash
ledgerexporter --start <start_ledger> --config-file <config_file_path>
```


Starts exporting from a specified number of ledgers before the latest ledger sequence number on the network.
```bash
ledgerexporter --from-last <number_of_ledgers> --config-file <config_file_path>
```


## Configuration File (config.toml)

```toml
network = "testnet"
urvisavla marked this conversation as resolved.
Show resolved Hide resolved
destination_url = "gcs://your-bucket-name"

[exporter_config]
ledgers_per_file = 64
files_per_partition = 10
```

## Exported Files

### File Organization:
- Ledgers are grouped into files, with the number of ledgers per file set by `ledgers_per_file`.
- Files are further organized into partitions, with the number of files per partition set by `files_per_partition`.

### Filename Structure:
- Filenames indicate the ledger range they contain, e.g., `0-63.xdr.gz` holds ledgers 0 to 63.
- Partition directories group files, e.g., `/0-639/` holds files for ledgers 0 to 639.

#### Example:
with `ledgers_per_file = 64` and `files_per_partition = 10`:
- Partition names: `/0-639`, `/640-1279`, ...
- Filenames: `/0-639/0-63.xdr.gz`, `/0-639/64-127.xdr.gz`, ...

#### Special Cases:

- If `ledgers_per_file` is set to 1, filenames will only contain the ledger number.
- If `files_per_partition` is set to 1, filenames will not contain the partition.

#### Note:
- Avoid changing `ledgers_per_file` and `files_per_partition` after configuration for consistency.

#### Retrieving Data:
- To locate a specific ledger sequence, calculate the partition name and ledger file name using `files_per_partition` and `ledgers_per_file`.
- The `GetObjectKeyFromSequenceNumber` function automates this calculation.

7 changes: 7 additions & 0 deletions exp/services/ledgerexporter/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
network = "testnet"
destination_url = "gcs://exporter-test/ledgers"

[exporter_config]
ledgers_per_file = 1
files_per_partition = 64000

139 changes: 139 additions & 0 deletions exp/services/ledgerexporter/internal/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package exporter

import (
"context"
_ "embed"
"fmt"
"os"
"os/signal"
"sync"
"syscall"

"github.com/pkg/errors"
"github.com/stellar/go/ingest/ledgerbackend"
_ "github.com/stellar/go/network"
supportlog "github.com/stellar/go/support/log"
)

var (
logger = supportlog.New().WithField("service", "ledger-exporter")
urvisavla marked this conversation as resolved.
Show resolved Hide resolved
)

type App struct {
config Config
backend ledgerbackend.LedgerBackend
destinationStorage DataStore
exportManager ExportManager
uploader Uploader
}

func NewApp() *App {
logger.SetLevel(supportlog.DebugLevel)

config := Config{}
err := config.LoadConfig()
logFatalIf(err, "Could not load configuration")

app := &App{config: config}
return app
}

func (a *App) init(ctx context.Context) {
a.destinationStorage = mustNewDataStore(ctx, &a.config)
a.backend = mustNewLedgerBackend(ctx, a.config)
a.exportManager = NewExportManager(a.config.ExporterConfig, a.backend)
a.uploader = NewUploader(a.destinationStorage, a.exportManager.GetMetaArchiveChannel())
}

func (a *App) close() {
//TODO: error handling
urvisavla marked this conversation as resolved.
Show resolved Hide resolved
a.destinationStorage.Close()
a.backend.Close()
}

func (a *App) Run() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

a.init(ctx)

var wg sync.WaitGroup
wg.Add(2)

go func() {
defer wg.Done()

err := a.uploader.Run(ctx)
if err != nil && !errors.Is(err, context.Canceled) {
logger.Errorf("Error executing Uploader: %v", err)
cancel()
}
}()

go func() {
defer wg.Done()

err := a.exportManager.Run(ctx, a.config.StartLedger, a.config.EndLedger)
if err != nil && !errors.Is(err, context.Canceled) {
logger.Errorf("Error executing ExportManager: %v", err)
cancel()
}
}()

go func() {
// Handle OS signals to gracefully terminate the service
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

for {
select {
case <-ctx.Done():
logger.Infof("Received context done signal")
return
urvisavla marked this conversation as resolved.
Show resolved Hide resolved
case sig := <-sigCh:
logger.Infof("Received signal: %v", sig)
cancel()
return
}
}
}()

wg.Wait()

a.close()

logger.Info("Shutting down ledger-exporter.")
}

func mustNewDataStore(ctx context.Context, config *Config) DataStore {
destinationStorage, err := NewDataStore(ctx, fmt.Sprintf("%s/%s", config.DestinationURL, config.Network))
logFatalIf(err, "Could not connect to destination storage")
return destinationStorage
}

// mustNewLedgerBackend Creates and initializes captive core ledger backend
// Currently, only supports captive-core as ledger backend
func mustNewLedgerBackend(ctx context.Context, config Config) ledgerbackend.LedgerBackend {
captiveConfig := config.GenerateCaptiveCoreConfig()

// Create a new captive core backend
backend, err := ledgerbackend.NewCaptive(captiveConfig)
logFatalIf(err, "Failed to create captive-core instance")

var ledgerRange ledgerbackend.Range
if config.EndLedger == 0 {
ledgerRange = ledgerbackend.UnboundedRange(config.StartLedger)
} else {
ledgerRange = ledgerbackend.BoundedRange(config.StartLedger, config.EndLedger)
}

err = backend.PrepareRange(ctx, ledgerRange)
logFatalIf(err, "Could not prepare captive core ledger backend")
return backend
}

func logFatalIf(err error, message string, args ...interface{}) {

Check failure on line 135 in exp/services/ledgerexporter/internal/app.go

View workflow job for this annotation

GitHub Actions / golangci

`logFatalIf` - `args` always receives `nil` (unparam)
if err != nil {
logger.WithError(err).Fatalf(message, args...)
}
}
Loading
Loading