[DEPRECATED] Go implementation of plcbundle
1package bundle
2
3import (
4 "fmt"
5 "path/filepath"
6 "time"
7
8 "tangled.org/atscan.net/plcbundle-go/internal/bundleindex"
9 "tangled.org/atscan.net/plcbundle-go/internal/plcclient"
10 "tangled.org/atscan.net/plcbundle-go/internal/types"
11)
12
13// Bundle represents a PLC bundle
14type Bundle struct {
15 BundleNumber int `json:"bundle_number"`
16 StartTime time.Time `json:"start_time"`
17 EndTime time.Time `json:"end_time"`
18 Operations []plcclient.PLCOperation `json:"-"`
19 DIDCount int `json:"did_count"`
20
21 Hash string `json:"hash"` // Chain hash (primary)
22 ContentHash string `json:"content_hash"` // Content hash
23 Parent string `json:"parent"`
24
25 CompressedHash string `json:"compressed_hash"`
26 CompressedSize int64 `json:"compressed_size"`
27 UncompressedSize int64 `json:"uncompressed_size"`
28 Cursor string `json:"cursor"`
29 BoundaryCIDs []string `json:"boundary_cids,omitempty"`
30 Compressed bool `json:"compressed"`
31 CreatedAt time.Time `json:"created_at"`
32}
33
34// GetFilePath returns the file path for this bundle
35func (b *Bundle) GetFilePath(bundleDir string) string {
36 return filepath.Join(bundleDir, fmt.Sprintf("%06d.jsonl.zst", b.BundleNumber))
37}
38
39// GetUncompressedFilePath returns the uncompressed file path
40func (b *Bundle) GetUncompressedFilePath(bundleDir string) string {
41 return filepath.Join(bundleDir, fmt.Sprintf("%06d.jsonl", b.BundleNumber))
42}
43
44// OperationCount returns the number of operations (always BUNDLE_SIZE for complete bundles)
45func (b *Bundle) OperationCount() int {
46 if len(b.Operations) > 0 {
47 return len(b.Operations)
48 }
49 return types.BUNDLE_SIZE
50}
51
52// CompressionRatio returns the compression ratio
53func (b *Bundle) CompressionRatio() float64 {
54 if b.CompressedSize == 0 {
55 return 0
56 }
57 return float64(b.UncompressedSize) / float64(b.CompressedSize)
58}
59
60// ValidateForSave performs validation before saving (no hash required)
61func (b *Bundle) ValidateForSave() error {
62 if b.BundleNumber < 1 {
63 return fmt.Errorf("invalid bundle number: %d", b.BundleNumber)
64 }
65 if len(b.Operations) != types.BUNDLE_SIZE {
66 return fmt.Errorf("invalid operation count: expected %d, got %d", types.BUNDLE_SIZE, len(b.Operations))
67 }
68 if b.StartTime.After(b.EndTime) {
69 return fmt.Errorf("start_time is after end_time")
70 }
71 return nil
72}
73
74// Validate performs full validation (including hashes)
75func (b *Bundle) Validate() error {
76 if err := b.ValidateForSave(); err != nil {
77 return err
78 }
79 if b.Hash == "" {
80 return fmt.Errorf("missing hash")
81 }
82 if b.CompressedHash == "" {
83 return fmt.Errorf("missing compressed hash")
84 }
85 return nil
86}
87
88// VerificationResult contains the result of bundle verification
89type VerificationResult struct {
90 BundleNumber int
91 Valid bool
92 HashMatch bool
93 FileExists bool
94 Error error
95 LocalHash string
96 ExpectedHash string
97}
98
99// ChainVerificationResult contains the result of chain verification
100type ChainVerificationResult struct {
101 Valid bool
102 ChainLength int
103 BrokenAt int
104 Error string
105 VerifiedBundles []int
106}
107
108// DirectoryScanResult contains results from scanning a directory
109type DirectoryScanResult struct {
110 BundleDir string
111 BundleCount int
112 FirstBundle int
113 LastBundle int
114 MissingGaps []int
115 TotalSize int64 // Compressed size
116 TotalUncompressed int64
117 IndexUpdated bool
118}
119
120// Config holds configuration for bundle operations
121type Config struct {
122 BundleDir string
123 HandleResolverURL string
124 VerifyOnLoad bool
125 AutoRebuild bool
126 AutoInit bool // Allow auto-creating empty repository
127 RebuildWorkers int // Number of workers for parallel rebuild (0 = auto-detect)
128 RebuildProgress func(current, total int) // Progress callback for rebuild
129 Logger types.Logger
130 Verbose bool
131 Quiet bool
132}
133
134// DefaultConfig returns default configuration
135func DefaultConfig(bundleDir string) *Config {
136 return &Config{
137 BundleDir: bundleDir,
138 HandleResolverURL: "https://quickdid.atscan.net",
139 VerifyOnLoad: true,
140 AutoRebuild: true,
141 AutoInit: false,
142 RebuildWorkers: 0, // 0 means auto-detect CPU count
143 RebuildProgress: nil, // No progress callback by default
144 Logger: nil,
145 Verbose: false,
146 Quiet: false,
147 }
148}
149
150// CloneOptions configures cloning behavior
151type CloneOptions struct {
152 RemoteURL string
153 Workers int
154 SkipExisting bool
155 ProgressFunc func(downloaded, total int, bytesDownloaded, bytesTotal int64)
156 SaveInterval time.Duration
157 Verbose bool
158 Logger types.Logger
159}
160
161// CloneResult contains cloning results
162type CloneResult struct {
163 RemoteBundles int
164 Downloaded int
165 Failed int
166 Skipped int
167 TotalBytes int64
168 Duration time.Duration
169 Interrupted bool
170 FailedBundles []int
171}
172
173// PLCOperationWithLocation contains an operation with its bundle/position metadata
174type PLCOperationWithLocation struct {
175 Operation plcclient.PLCOperation
176 Bundle int
177 Position int
178}
179
180func (b *Bundle) ToMetadata() *bundleindex.BundleMetadata {
181 return &bundleindex.BundleMetadata{
182 BundleNumber: b.BundleNumber,
183 StartTime: b.StartTime,
184 EndTime: b.EndTime,
185 OperationCount: b.OperationCount(),
186 DIDCount: b.DIDCount,
187 Hash: b.Hash, // Chain hash
188 ContentHash: b.ContentHash, // Content hash
189 Parent: b.Parent,
190 CompressedHash: b.CompressedHash,
191 CompressedSize: b.CompressedSize,
192 UncompressedSize: b.UncompressedSize,
193 Cursor: b.Cursor,
194 CreatedAt: b.CreatedAt,
195 }
196}
197
198// ResolveDIDResult contains DID resolution with timing metrics
199type ResolveDIDResult struct {
200 Document *plcclient.DIDDocument
201 LatestOperation *plcclient.PLCOperation
202 MempoolTime time.Duration
203 IndexTime time.Duration
204 LoadOpTime time.Duration
205 TotalTime time.Duration
206 ResolvedHandle string
207 Source string // "mempool" or "bundle"
208 BundleNumber int // if from bundle
209 Position int // if from bundle
210}
211
212type resolverTiming struct {
213 totalTime int64
214 mempoolTime int64
215 indexTime int64
216 loadOpTime int64
217 source string // "mempool" or "bundle"
218}