upload first, then store the key as virtual fk

This commit is contained in:
Giau. Tran Minh
2026-05-05 15:27:47 +00:00
parent 39bcbbc359
commit 6802bf68f8
30 changed files with 539 additions and 685 deletions

View File

@@ -169,6 +169,25 @@ func ({{ $receiver }} *{{ $builder }}) sqlSave(ctx context.Context) (_node {{ if
{{- xtemplate $tmpl $ }}
{{- end }}
{{- end }}
{{- if and $one $.HasBlobFields }}
_blobs := ent.NewBlobBulkWriter({{ $mutation }}.blobOpeners.{{ $.Name }})
{{- range $f := $.BlobFields }}
if r, ok := {{ $mutation }}.{{ $f.StructField }}(); ok {
{{- if $f.HasBlobKey }}
key, err := {{ $.Package }}.{{ $f.BlobKeyName }}(ctx)
if err != nil {
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: generating blob key for {{ $f.Name }}: %w", err), _blobs.Close())
}
{{- else }}
key := uuid.NewString()
{{- end }}
if err := _blobs.Write(ctx, {{ $.Package }}.{{ $f.Constant }}, key, r); err != nil {
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: writing blob for {{ $f.Name }}: %w", err), _blobs.Close())
}
_spec.SetField("{{ $f.Name }}_key", field.TypeString, key)
}
{{- end }}
{{- end }}
{{- if $one }}
_node = &{{ $.Name }}{config: {{ $receiver }}.config}
_spec.Assign = _node.assignValues
@@ -184,72 +203,17 @@ func ({{ $receiver }} *{{ $builder }}) sqlSave(ctx context.Context) (_node {{ if
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
{{- if and $one $.HasBlobFields }}
return {{ $zero }}, errors.Join(err, _blobs.Close())
{{- else }}
return {{ $zero }}, err
{{- end }}
}
{{ $mutation }}.done = true
{{- if and $one $.HasBlobFields }}
{{- $blobFields := $.BlobFields }}
{{- if gt (len $blobFields) 1 }}
type blobWritten struct { field string; key string }
var _blobWritten []blobWritten
_blobCleanup := func(ctx context.Context) error {
var errs []error
for _, bw := range _blobWritten {
b, err := {{ $mutation }}.blobOpeners.{{ $.Name }}(ctx, bw.field)
if err != nil {
errs = append(errs, err)
continue
}
errs = append(errs, b.Delete(ctx, bw.key), b.Close())
}
return errors.Join(errs...)
}
{{- end }}
{{- range $i, $f := $blobFields }}
if r, ok := {{ $mutation }}.{{ $f.StructField }}(); ok {
b, err := {{ $mutation }}.blobOpeners.{{ $.Name }}(ctx, {{ $.Package }}.{{ $f.Constant }})
if err != nil {
{{- if gt (len $blobFields) 1 }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: opening blob bucket for {{ $f.Name }}: %w", err), _blobCleanup(ctx))
{{- else }}
return nil, fmt.Errorf("{{ $pkg }}: opening blob bucket for {{ $f.Name }}: %w", err)
{{- end }}
}
key, err := _node.{{ $f.StructField }}Key(ctx)
if err != nil {
{{- if gt (len $blobFields) 1 }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: blob key for {{ $f.Name }}: %w", err), b.Close(), _blobCleanup(ctx))
{{- else }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: blob key for {{ $f.Name }}: %w", err), b.Close())
{{- end }}
}
w, err := b.NewWriter(ctx, key)
if err != nil {
{{- if gt (len $blobFields) 1 }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: creating writer for {{ $f.Name }}: %w", err), b.Close(), _blobCleanup(ctx))
{{- else }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: creating writer for {{ $f.Name }}: %w", err), b.Close())
{{- end }}
}
if _, err := io.Copy(w, r); err != nil {
{{- if gt (len $blobFields) 1 }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: writing blob for {{ $f.Name }}: %w", err), w.Close(), b.Close(), _blobCleanup(ctx))
{{- else }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: writing blob for {{ $f.Name }}: %w", err), w.Close(), b.Close())
{{- end }}
}
if err := errors.Join(w.Close(), b.Close()); err != nil {
{{- if gt (len $blobFields) 1 }}
return nil, errors.Join(fmt.Errorf("{{ $pkg }}: closing blob for {{ $f.Name }}: %w", err), _blobCleanup(ctx))
{{- else }}
return nil, fmt.Errorf("{{ $pkg }}: closing blob for {{ $f.Name }}: %w", err)
{{- end }}
}
{{- if gt (len $blobFields) 1 }}
_blobWritten = append(_blobWritten, blobWritten{field: {{ $.Package }}.{{ $f.Constant }}, key: key})
{{- end }}
}
{{- end }}
if err := _blobs.Close(); err != nil {
return nil, err
}
{{- end }}
return _node, nil
}