Conditions | 10 |
Total Lines | 65 |
Code Lines | 40 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like postgres.*Postgres.Repair often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | package postgres |
||
45 | func (p *Postgres) Repair(ctx context.Context, config *RepairConfig) (*RepairResult, error) { |
||
46 | if config == nil { |
||
47 | config = DefaultRepairConfig() |
||
48 | } |
||
49 | |||
50 | // Validate BatchSize - don't accept 0 or negative values |
||
51 | if config.BatchSize <= 0 { |
||
52 | config.BatchSize = 1000 // Use default value |
||
53 | slog.InfoContext(ctx, "Invalid BatchSize provided, using default", slog.Int("default_batch_size", 1000)) |
||
54 | } |
||
55 | |||
56 | result := &RepairResult{ |
||
57 | Errors: make([]error, 0), |
||
58 | } |
||
59 | |||
60 | slog.InfoContext(ctx, "Starting PostgreSQL transaction ID counter repair", |
||
61 | slog.Bool("dry_run", config.DryRun), |
||
62 | slog.Int("batch_size", config.BatchSize)) |
||
63 | |||
64 | // Step 1: Get current PostgreSQL XID |
||
65 | currentXID, err := p.getCurrentPostgreSQLXID(ctx) |
||
66 | if err != nil { |
||
67 | return result, fmt.Errorf("failed to get current PostgreSQL XID: %w", err) |
||
|
|||
68 | } |
||
69 | |||
70 | if config.Verbose { |
||
71 | slog.InfoContext(ctx, "Current PostgreSQL transaction ID", slog.Uint64("current_xid", currentXID)) |
||
72 | } |
||
73 | |||
74 | // Step 2: Get maximum referenced XID from transactions table |
||
75 | maxReferencedXID, err := p.getMaxReferencedXID(ctx) |
||
76 | if err != nil { |
||
77 | result.Errors = append(result.Errors, fmt.Errorf("failed to get max referenced XID: %w", err)) |
||
78 | return result, nil |
||
79 | } |
||
80 | |||
81 | if config.Verbose { |
||
82 | slog.InfoContext(ctx, "Maximum referenced transaction ID", slog.Uint64("max_referenced_xid", maxReferencedXID)) |
||
83 | } |
||
84 | |||
85 | // Step 3: Advance XID counter if needed |
||
86 | if maxReferencedXID > currentXID { |
||
87 | counterDelta := int(maxReferencedXID - currentXID + 1000) // Add safety buffer |
||
88 | |||
89 | if config.DryRun { |
||
90 | slog.InfoContext(ctx, "Would advance XID counter", |
||
91 | slog.Int("counter_delta", counterDelta), |
||
92 | slog.Uint64("target_xid", maxReferencedXID+1000)) |
||
93 | result.CreatedTxIdFixed = counterDelta |
||
94 | } else { |
||
95 | if err := p.advanceXIDCounterByDelta(ctx, counterDelta, config); err != nil { |
||
96 | result.Errors = append(result.Errors, fmt.Errorf("failed to advance XID counter: %w", err)) |
||
97 | } else { |
||
98 | result.CreatedTxIdFixed = counterDelta |
||
99 | } |
||
100 | } |
||
101 | } else { |
||
102 | slog.InfoContext(ctx, "No XID counter advancement needed") |
||
103 | } |
||
104 | |||
105 | slog.InfoContext(ctx, "PostgreSQL transaction ID counter repair completed", |
||
106 | slog.Int("transactions_advanced", result.CreatedTxIdFixed), |
||
107 | slog.Int("errors", len(result.Errors))) |
||
108 | |||
109 | return result, nil |
||
110 | } |
||
184 |