You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: processingmedia.go
    path of file: ./repos/gotosocial/internal/media
    
    the code of the file until where you have to start completion: // GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package media

import (
	"bytes"
	"context"
	"errors"
	"image/jpeg"
	"io"
	"time"

	errorsv2 "codeberg.org/gruf/go-errors/v2"
	"codeberg.org/gruf/go-runners"
	"codeberg.org/superseriousbusiness/exif-terminator"
	"github.com/disintegration/imaging"
	"github.com/h2non/filetype"
	"github.com/superseriousbusiness/gotosocial/internal/gtserror"
	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
	"github.com/superseriousbusiness/gotosocial/internal/log"
	"github.com/superseriousbusiness/gotosocial/internal/storage"
	"github.com/superseriousbusiness/gotosocial/internal/uris"
	"github.com/superseriousbusiness/gotosocial/internal/util"
)

// ProcessingMedia represents a piece of media
// currently being processed. It exposes functions
// for retrieving data from the process.
type ProcessingMedia struct {
	media   *gtsmodel.MediaAttachment // processing media attachment details
	dataFn  DataFunc                  // load-data function, returns media stream
	recache bool                      // recaching existing (uncached) media
	done    bool                      // done is set when process finishes with non ctx canceled type error
	proc    runners.Proc
    
func (p *ProcessingMedia) load(ctx context.Context) (*gtsmodel.MediaAttachment, bool, error) {
	var (
		done bool
		err  error
	)

	err = p.proc.Process(func() error {
		if p.done {
			// Already proc'd.
			return p.err
		}

		defer func() {
			// This is only done when ctx NOT cancelled.
			done = err == nil || !errorsv2.IsV2(err,
				context.Canceled,
				context.DeadlineExceeded,
			)

			if !done {
				return
			}

			// Store final values.
			p.done = true
			p.err = err
		}()

		// Gather errors as we proceed.
		var errs = gtserror.NewMultiError(4)

		// Attempt to store media and calculate
		// full-size media attachment details.
		//
		// This will update p.media as it goes.
		storeErr := p.store(ctx)
		if storeErr != nil {
			errs.Append(storeErr)
		}

		// Finish processing by reloading media into
		// memory to get dimension and generate a thumb.
		//
		// This will update p.media as it goes.
		if finishErr := p.finish(ctx); finishErr != nil {
			errs.Append(finishErr)
		}

		// If this isn't a file we were able to process,
		// we may have partially stored it (eg., it's a
		// jpeg, which is fine, but streaming it to storage
		// was interrupted halfway through and so it was
		// never decoded). Try to clean up in this case.
		if p.media.Type == gtsmodel.FileTypeUnknown {
			deleteErr := p.mgr.state.Storage.Delete(ctx, p.media.File.Path)
			if deleteErr != nil && !errors.Is(deleteErr, storage.ErrNotFound) {
				errs.Append(deleteErr)
			}
		}

		var dbErr error
		switch {
		case !p.recache:
			// First time caching this attachment, insert it.
			dbErr = p.mgr.state.DB.PutAttachment(ctx, p.media)

		case p.recache && len(errs) == 0:
			// Existing attachment we're recaching, update it.
			//
			// (We only want to update if everything went OK so far,
			// otherwise we'd better leave previous version alone.)
			dbErr = p.mgr.state.DB.UpdateAttachment(ctx, p.media)
		}

		if dbErr != nil {
			errs.Append(dbErr)
		}

		err = errs.Combine()
		return err
	})

	return p.media, done, err
}