(ctx context.Context, lease *litestream.Lease, etag string)
| 229 | } |
| 230 | |
| 231 | func (l *Leaser) writeLease(ctx context.Context, lease *litestream.Lease, etag string) (string, error) { |
| 232 | key := l.lockKey() |
| 233 | |
| 234 | data, err := json.Marshal(lease) |
| 235 | if err != nil { |
| 236 | return "", fmt.Errorf("marshal lock file: %w", err) |
| 237 | } |
| 238 | |
| 239 | input := &s3.PutObjectInput{ |
| 240 | Bucket: aws.String(l.Bucket), |
| 241 | Key: aws.String(key), |
| 242 | Body: bytes.NewReader(data), |
| 243 | ContentType: aws.String("application/json"), |
| 244 | } |
| 245 | |
| 246 | if etag == "" { |
| 247 | input.IfNoneMatch = aws.String("*") |
| 248 | } else { |
| 249 | input.IfMatch = aws.String(etag) |
| 250 | } |
| 251 | |
| 252 | out, err := l.s3.PutObject(ctx, input) |
| 253 | if err != nil { |
| 254 | if isPreconditionFailed(err) { |
| 255 | return "", &litestream.LeaseExistsError{} |
| 256 | } |
| 257 | return "", fmt.Errorf("put lock file: %w", err) |
| 258 | } |
| 259 | |
| 260 | newETag := "" |
| 261 | if out.ETag != nil { |
| 262 | newETag = *out.ETag |
| 263 | } |
| 264 | |
| 265 | return newETag, nil |
| 266 | } |
| 267 | |
| 268 | func isPreconditionFailed(err error) bool { |
| 269 | var apiErr smithy.APIError |
no test coverage detected