Skip to content

feat: archivistactl import - #358

Open
kairoaraujo wants to merge 2 commits into
in-toto:mainfrom
kairoaraujo:feat/import
Open

feat: archivistactl import#358
kairoaraujo wants to merge 2 commits into
in-toto:mainfrom
kairoaraujo:feat/import

Conversation

@kairoaraujo

@kairoaraujo kairoaraujo commented Aug 19, 2024

Copy link
Copy Markdown
Collaborator

What this PR does / why we need it

Introduces a new archivistactl import

It allows Archivista users to import DSSE Envelopes directly to the Archivista database.

The feature allows direct import, which can help import huge amounts of data as it uses concurrency (go routines) to process.

Performance examples

Importing 2100 new DSSE Envelopes

Using default: --max-concurrent 3
Screenshot 2024-08-19 at 13 46 23

Using --max-concurrent 10
Screenshot 2024-08-19 at 13 51 28

Which issue(s) this PR fixes (optional)

(optional, using fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when the PR gets merged)*

Related #319

Acceptance Criteria Met

  • Docs changes if needed
  • Testing changes if needed
  • All workflow checks passing (automatically enforced)
  • All review conversations resolved (automatically enforced)
  • DCO Sign-off

Special notes for your reviewer:

TODO:

  • Unit Tests
  • Sub-features (nice to have)
    • --exist-first fail in the first import error instead of skipping

I can add the TODO as new commits or as new PRs.

@codecov

codecov Bot commented Aug 19, 2024

Copy link
Copy Markdown

Codecov Report

Attention: Patch coverage is 7.00000% with 93 lines in your changes missing coverage. Please review.

Project coverage is 1.64%. Comparing base (a035c62) to head (f670f06).
Report is 152 commits behind head on main.

Files Patch % Lines
cmd/archivistactl/cmd/import.go 7.00% 93 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #358       +/-   ##
==========================================
- Coverage   82.40%   1.64%   -80.76%     
==========================================
  Files          10     121      +111     
  Lines         358   28956    +28598     
==========================================
+ Hits          295     477      +182     
- Misses         43   28422    +28379     
- Partials       20      57       +37     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kairoaraujo
kairoaraujo marked this pull request as draft August 19, 2024 13:30
@kairoaraujo
kairoaraujo force-pushed the feat/import branch 2 times, most recently from d8ff65a to fe986e1 Compare August 20, 2024 14:01
@kairoaraujo
kairoaraujo marked this pull request as ready for review August 21, 2024 05:43
Introduces a new `archivistactl` import

It allows Archivista users to import DSSE Envelopes directly to the
Archivista database.

The feature allows direct import, which can help importing huge amount
of data as it use concurrency (go routines) to process.

Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>
@mikhailswift

mikhailswift commented Nov 11, 2024

Copy link
Copy Markdown
Member

Definitely like this -- there's been a few times where I've hacked this in but never actually got it in a mergable state.

I think one thing we may eventually want to do is also support smarter bulk loading on the server side. We can do some better SQL optimizations when we know we're going to load in a bunch of data, but we can worry about that later

@netlify

netlify Bot commented Jul 5, 2026

Copy link
Copy Markdown

Deploy Preview for archivista-dev ready!

Name Link
🔨 Latest commit 1ebf693
🔍 Latest deploy log https://app.netlify.com/projects/archivista-dev/deploys/6a49fdfe44882700084d50c6
😎 Deploy Preview https://deploy-preview-358--archivista-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new archivistactl import subcommand intended to bulk-import DSSE envelopes directly into the Archivista SQL-backed metadata store, using a concurrency limit to improve throughput for large folders.

Changes:

  • Introduces archivistactl import command with --from-dir, --db-uri, and --max-concurrent flags.
  • Implements concurrent directory walking + per-file DSSE parsing and storage into the SQL store.
  • Adds DB client initialization logic to connect to MySQL/Postgres via sqlstore.NewEntClient.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +37 to +43
importCmd = &cobra.Command{
Use: "import",
Short: "import dsses to the Archivista DB server",
SilenceUsage: true,
Args: cobra.MaximumNArgs(2),
RunE: importDsse,
}
Comment on lines +46 to +53
func init() {
rootCmd.AddCommand(importCmd)
importCmd.PersistentFlags().StringP("from-dir", "", "", "Directory to import from. Example: /path/to/directory")
importCmd.PersistentFlags().StringP("db-uri", "", "", "Database URI to import to. Supported schemes: mysql, psql. Example: mysql://user:password@localhost:3306/testify")
importCmd.PersistentFlags().IntP("max-concurrent", "", 3, "Maximum number of concurrent imports.")
err := importCmd.MarkPersistentFlagRequired("db-uri")
cobra.CheckErr(err)
}
Comment on lines +93 to +102
switch strings.ToUpper(purl.Scheme) {
case "MYSQL":
scheme = "MYSQL"
uri = purl.User.String() + "@" + purl.Host + purl.Path
case "PSQL":
scheme = "PSQL"
uri = dbURI
default:
return nil, fmt.Errorf("unsupported database scheme %s", purl.Scheme)
}
Comment on lines +179 to +187
ec, err := dbClient(dbURI)
if err != nil {
return err
}

sqlStore, _, err := sqlstore.New(context.Background(), ec)
if err != nil {
return err
}
Comment on lines +189 to +195
max, err := ccmd.Flags().GetInt("max-concurrent")
if err != nil {
fmt.Println("Failed to get max-concurrent flag", err)
}
fmt.Print("\nImporting DSSes from folder", sourceDir, " to the database server")
fmt.Print("\nMax concurrent imports: ", max, "\n\n")
importFile(sourceDir, sqlStore, max)
Comment on lines +117 to +120
func importFile(path string, sqlStore *sqlstore.Store, maxConcurrent int) {
fpaths, _ := walkDir(path)
var wg sync.WaitGroup
sem := make(chan struct{}, maxConcurrent) // Buffered channel acting as a semaphore
Comment on lines +141 to +158
if envelope.PayloadType != "" {
ngitoid, err := gitoid.New(bytes.NewReader(file), gitoid.WithContentLength(int64(len(file))), gitoid.WithSha256())
if err != nil {
fmt.Println("Skipping file: "+fpath+" cannot generate valid GitOID", fpath)
return
}
err = sqlStore.Store(context.Background(), ngitoid.String(), file)
if err != nil {
// if failed due to duplicate entry, skip
if strings.Contains(err.Error(), "Duplicate entry") {
fmt.Println("Skipping file: " + fpath + " cannot store duplicated entry")
} else {
fmt.Println("Skipping file: "+fpath+" failed to import.", err)
}
return
}
}
fmt.Println("Successfully imported", fpath)
Comment on lines +46 to +53
func init() {
rootCmd.AddCommand(importCmd)
importCmd.PersistentFlags().StringP("from-dir", "", "", "Directory to import from. Example: /path/to/directory")
importCmd.PersistentFlags().StringP("db-uri", "", "", "Database URI to import to. Supported schemes: mysql, psql. Example: mysql://user:password@localhost:3306/testify")
importCmd.PersistentFlags().IntP("max-concurrent", "", 3, "Maximum number of concurrent imports.")
err := importCmd.MarkPersistentFlagRequired("db-uri")
cobra.CheckErr(err)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants