@@ -241,9 +241,7 @@ func (fms *FileManagerService) UpdateFile(
241241 return fms .sendUpdateFileRequest (ctx , fileToUpdate )
242242 }
243243
244- // TODO: Add config parameter for chunk size
245- var chunkSize uint32 = 2097152 // 2MB
246- return fms .sendUpdateFileStream (ctx , fileToUpdate , chunkSize )
244+ return fms .sendUpdateFileStream (ctx , fileToUpdate , fms .agentConfig .Client .Grpc .FileChunkSize )
247245}
248246
249247func (fms * FileManagerService ) sendUpdateFileRequest (
@@ -314,6 +312,10 @@ func (fms *FileManagerService) sendUpdateFileStream(
314312 fileToUpdate * mpi.File ,
315313 chunkSize uint32 ,
316314) error {
315+ if chunkSize == 0 {
316+ return fmt .Errorf ("file chunk size must be greater than zero" )
317+ }
318+
317319 updateFileStreamClient , err := fms .fileServiceClient .UpdateFileStream (ctx )
318320 if err != nil {
319321 return err
@@ -441,10 +443,12 @@ func (fms *FileManagerService) readChunk(
441443 return mpi.FileDataChunk_Content {}, fmt .Errorf ("failed to read chunk: %w" , err )
442444 }
443445
446+ slog .DebugContext (ctx , "No more data to read from file" )
447+
444448 return mpi.FileDataChunk_Content {}, nil
445449 }
446450
447- slog .DebugContext (ctx , "Read chunk" , "chunkID " , chunkID , "chunk_size" , len (buf ))
451+ slog .DebugContext (ctx , "Read file chunk" , "chunk_id " , chunkID , "chunk_size" , len (buf ))
448452
449453 chunk := mpi.FileDataChunk_Content {
450454 Content : & mpi.FileDataChunkContent {
@@ -628,38 +632,51 @@ func (fms *FileManagerService) executeFileActions(ctx context.Context) error {
628632}
629633
630634func (fms * FileManagerService ) fileUpdate (ctx context.Context , file * mpi.File ) error {
635+ slog .DebugContext (ctx , "Updating file" , "file" , file .GetFileMeta ().GetName ())
631636 if file .GetFileMeta ().GetSize () <= int64 (fms .agentConfig .Client .Grpc .MaxMessageReceiveSize ) {
632- backOffCtx , backoffCancel := context .WithTimeout (ctx , fms .agentConfig .Client .Backoff .MaxElapsedTime )
633- defer backoffCancel ()
634-
635- getFile := func () (* mpi.GetFileResponse , error ) {
636- return fms .fileServiceClient .GetFile (ctx , & mpi.GetFileRequest {
637- MessageMeta : & mpi.MessageMeta {
638- MessageId : id .GenerateMessageID (),
639- CorrelationId : logger .GetCorrelationID (ctx ),
640- Timestamp : timestamppb .Now (),
641- },
642- FileMeta : file .GetFileMeta (),
643- })
644- }
637+ return fms .getFile (ctx , file )
638+ }
645639
646- getFileResp , getFileErr := backoff .RetryWithData (
647- getFile ,
648- backoffHelpers .Context (backOffCtx , fms .agentConfig .Client .Backoff ),
649- )
640+ return fms .getChunkedFile (ctx , file )
641+ }
650642
651- if getFileErr != nil {
652- return fmt .Errorf ("error getting file data for %s: %w" , file .GetFileMeta (), getFileErr )
653- }
643+ func (fms * FileManagerService ) getFile (ctx context.Context , file * mpi.File ) error {
644+ slog .DebugContext (ctx , "Getting file" , "file" , file .GetFileMeta ().GetName ())
654645
655- if writeErr := fms .fileOperator .Write (ctx , getFileResp .GetContents ().GetContents (),
656- file .GetFileMeta ()); writeErr != nil {
657- return writeErr
658- }
646+ backOffCtx , backoffCancel := context .WithTimeout (ctx , fms .agentConfig .Client .Backoff .MaxElapsedTime )
647+ defer backoffCancel ()
648+
649+ getFile := func () (* mpi.GetFileResponse , error ) {
650+ return fms .fileServiceClient .GetFile (ctx , & mpi.GetFileRequest {
651+ MessageMeta : & mpi.MessageMeta {
652+ MessageId : id .GenerateMessageID (),
653+ CorrelationId : logger .GetCorrelationID (ctx ),
654+ Timestamp : timestamppb .Now (),
655+ },
656+ FileMeta : file .GetFileMeta (),
657+ })
658+ }
659+
660+ getFileResp , getFileErr := backoff .RetryWithData (
661+ getFile ,
662+ backoffHelpers .Context (backOffCtx , fms .agentConfig .Client .Backoff ),
663+ )
664+
665+ if getFileErr != nil {
666+ return fmt .Errorf ("error getting file data for %s: %w" , file .GetFileMeta (), getFileErr )
667+ }
659668
660- return fms .validateFileHash (file .GetFileMeta ().GetName ())
669+ if writeErr := fms .fileOperator .Write (ctx , getFileResp .GetContents ().GetContents (),
670+ file .GetFileMeta ()); writeErr != nil {
671+ return writeErr
661672 }
662673
674+ return fms .validateFileHash (file .GetFileMeta ().GetName ())
675+ }
676+
677+ func (fms * FileManagerService ) getChunkedFile (ctx context.Context , file * mpi.File ) error {
678+ slog .DebugContext (ctx , "Getting chunked file" , "file" , file .GetFileMeta ().GetName ())
679+
663680 stream , err := fms .fileServiceClient .GetFileStream (ctx , & mpi.GetFileRequest {
664681 MessageMeta : & mpi.MessageMeta {
665682 MessageId : id .GenerateMessageID (),
@@ -673,28 +690,52 @@ func (fms *FileManagerService) fileUpdate(ctx context.Context, file *mpi.File) e
673690 }
674691
675692 // Get header chunk first
676- chunk := & mpi.FileDataChunk {}
677- recvError := stream .RecvMsg (chunk )
678- if recvError != nil {
679- return recvError
693+ headerChunk , recvHeaderChunkError := stream .Recv ()
694+ if recvHeaderChunkError != nil {
695+ return recvHeaderChunkError
696+ }
697+
698+ slog .DebugContext (ctx , "File header chunk received" , "header_chunk" , headerChunk )
699+
700+ header := headerChunk .GetHeader ()
701+
702+ writeChunkedFileError := fms .writeChunkedFile (ctx , file , header , stream )
703+ if writeChunkedFileError != nil {
704+ return writeChunkedFileError
680705 }
681706
682- header := chunk .GetHeader ()
707+ return nil
708+ }
683709
684- filePermissions := files .FileMode (header .GetFileMeta ().GetPermissions ())
685- createFileDirectoriesError := fms .fileOperator .CreateFileDirectories (ctx , header .GetFileMeta (), filePermissions )
710+ func (fms * FileManagerService ) writeChunkedFile (
711+ ctx context.Context ,
712+ file * mpi.File ,
713+ header * mpi.FileDataChunkHeader ,
714+ stream grpc2.ServerStreamingClient [mpi.FileDataChunk ],
715+ ) error {
716+ filePermissions := files .FileMode (file .GetFileMeta ().GetPermissions ())
717+ createFileDirectoriesError := fms .fileOperator .CreateFileDirectories (ctx , file .GetFileMeta (), filePermissions )
686718 if createFileDirectoriesError != nil {
687719 return createFileDirectoriesError
688720 }
689721
690- fileToWrite , openError := os .OpenFile (header .GetFileMeta ().GetName (), os .O_WRONLY , filePermissions )
691- if openError != nil {
692- return openError
722+ fileToWrite , createError := os .Create (file .GetFileMeta ().GetName ())
723+ defer func () {
724+ closeError := fileToWrite .Close ()
725+ if closeError != nil {
726+ slog .WarnContext (
727+ ctx , "Failed to close file" ,
728+ "file" , file .GetFileMeta ().GetName (),
729+ "error" , closeError ,
730+ )
731+ }
732+ }()
733+ if createError != nil {
734+ return createError
693735 }
694736
695737 for i := uint32 (0 ); i < header .GetChunks (); i ++ {
696- chunk := & mpi.FileDataChunk {}
697- recvError := stream .RecvMsg (chunk )
738+ chunk , recvError := stream .Recv ()
698739 if recvError != nil {
699740 return recvError
700741 }
0 commit comments