@@ -812,40 +812,53 @@ func (r *Runner) verifyProcessCleanup(pid int) {
812812
813813// predict returns a channel that will receive the prediction response and an initial prediction response
814814// populated with the relevant fields from the request
815- func (r * Runner ) predict (req PredictionRequest ) (chan PredictionResponse , * PredictionResponse , error ) {
815+ func (r * Runner ) predict (reqID string ) (chan PredictionResponse , * PredictionResponse , error ) {
816816 log := r .logger .Sugar ()
817817 r .mu .Lock ()
818818 defer r .mu .Unlock ()
819819
820- log .Tracew ("runner.predict called" , "prediction_id" , req . ID , "status" , r .status )
820+ log .Tracew ("runner.predict called" , "prediction_id" , reqID , "status" , r .status )
821821
822822 // Prediction must be pre-allocated by manager
823- pending , exists := r .pending [req . ID ]
823+ pending , exists := r .pending [reqID ]
824824 if ! exists {
825- return nil , nil , fmt .Errorf ("prediction %s not allocated" , req . ID )
825+ return nil , nil , fmt .Errorf ("prediction %s not allocated" , reqID )
826826 }
827827
828- log .Tracew ("prediction found in pending" , "prediction_id" , req .ID )
828+ if pending .request .ID != reqID {
829+ return nil , nil , fmt .Errorf ("prediction ID mismatch: expected %s, got %s" , reqID , pending .request .ID )
830+ }
831+
832+ pending .mu .Lock ()
833+ defer pending .mu .Unlock ()
834+
835+ log .Tracew ("prediction found in pending" , "prediction_id" , reqID )
829836
830837 // Process input paths (base64 and URL inputs)
831838 inputPaths := make ([]string , 0 )
832- input , err := ProcessInputPaths (req .Input , r .doc , & inputPaths , Base64ToInput )
833- if err != nil {
834- return nil , nil , fmt .Errorf ("failed to process base64 inputs: %w" , err )
835- }
836- input , err = ProcessInputPaths (input , r .doc , & inputPaths , URLToInput )
837- if err != nil {
838- return nil , nil , fmt .Errorf ("failed to process URL inputs: %w" , err )
839+ if r .doc == nil {
840+ log .Errorw ("OpenAPI schema not available for input processing - cannot convert base64 or URL inputs" , "prediction_id" , reqID )
841+ } else {
842+ // Process base64 inputs first, then URL inputs (to allow URL inputs to reference base64-decoded files)
843+ input , err := ProcessInputPaths (pending .request .Input , r .doc , & inputPaths , Base64ToInput )
844+ if err != nil {
845+ return nil , nil , fmt .Errorf ("failed to process base64 inputs: %w" , err )
846+ }
847+
848+ input , err = ProcessInputPaths (input , r .doc , & inputPaths , URLToInput )
849+ if err != nil {
850+ return nil , nil , fmt .Errorf ("failed to process URL inputs: %w" , err )
851+ }
852+ pending .request .Input = input
839853 }
840- req .Input = input
841854 pending .inputPaths = inputPaths
842855
843- // Write prediction request to file (async like original)
844- requestFile := fmt .Sprintf ("request-%s.json" , req . ID )
845- log .Debugw ("writing prediction request file" , "prediction_id" , req . ID , "file" , requestFile )
856+ // Write prediction request to file
857+ requestFile := fmt .Sprintf ("request-%s.json" , reqID )
858+ log .Debugw ("writing prediction request file" , "prediction_id" , reqID , "file" , requestFile )
846859 requestPath := path .Join (r .runnerCtx .workingdir , requestFile )
847860
848- requestData , err := json .Marshal (req )
861+ requestData , err := json .Marshal (pending . request )
849862 if err != nil {
850863 return nil , nil , fmt .Errorf ("failed to marshal request: %w" , err )
851864 }
@@ -854,13 +867,13 @@ func (r *Runner) predict(req PredictionRequest) (chan PredictionResponse, *Predi
854867 return nil , nil , fmt .Errorf ("failed to write request file: %w" , err )
855868 }
856869
857- log .Tracew ("wrote prediction request file" , "prediction_id" , req . ID , "path" , requestPath , "working_dir" , r .runnerCtx .workingdir , "request_data" , string (requestData ))
870+ log .Tracew ("wrote prediction request file" , "prediction_id" , reqID , "path" , requestPath , "working_dir" , r .runnerCtx .workingdir , "request_data" , string (requestData ))
858871
859872 // Debug: Check if file actually exists and list directory contents
860873 if _ , err := os .Stat (requestPath ); err != nil {
861- log .Tracew ("ERROR: written request file does not exist" , "prediction_id" , req . ID , "path" , requestPath , "error" , err )
874+ log .Tracew ("ERROR: written request file does not exist" , "prediction_id" , reqID , "path" , requestPath , "error" , err )
862875 } else {
863- log .Tracew ("confirmed request file exists" , "prediction_id" , req . ID , "path" , requestPath )
876+ log .Tracew ("confirmed request file exists" , "prediction_id" , reqID , "path" , requestPath )
864877 }
865878
866879 // Debug: List all files in working directory
@@ -869,25 +882,14 @@ func (r *Runner) predict(req PredictionRequest) (chan PredictionResponse, *Predi
869882 for i , entry := range entries {
870883 fileNames [i ] = entry .Name ()
871884 }
872- log .Tracew ("working directory contents after write" , "prediction_id" , req .ID , "working_dir" , r .runnerCtx .workingdir , "files" , fileNames )
873- }
874-
875- // Update pending prediction with request details
876- pending .request = req
877-
878- now := time .Now ().Format (config .TimeFormat )
879- if pending .request .CreatedAt == "" {
880- pending .request .CreatedAt = now
881- }
882- if pending .request .StartedAt == "" {
883- pending .request .StartedAt = now
885+ log .Tracew ("working directory contents after write" , "prediction_id" , reqID , "working_dir" , r .runnerCtx .workingdir , "files" , fileNames )
884886 }
885887
886- log .Tracew ("returning prediction channel" , "prediction_id" , req . ID )
888+ log .Tracew ("returning prediction channel" , "prediction_id" , reqID )
887889 initialResponse := & PredictionResponse {
888890 Status : PredictionStarting ,
889891 }
890- initialResponse .populateFromRequest (req )
892+ initialResponse .populateFromRequest (pending . request )
891893 return pending .c , initialResponse , nil
892894}
893895
@@ -970,14 +972,23 @@ func (r *Runner) updateSchema() {
970972 r .mu .Lock ()
971973 defer r .mu .Unlock ()
972974
975+ log := r .logger .Sugar ()
973976 schemaPath := filepath .Join (r .runnerCtx .workingdir , "openapi.json" )
977+ log .Tracew ("attempting to read openapi.json" , "path" , schemaPath )
978+
974979 if schemaData , err := os .ReadFile (schemaPath ); err == nil { //nolint:gosec // expected dynamic path
975980 r .schema = string (schemaData )
981+ log .Tracew ("successfully read openapi.json" , "schema_length" , len (schemaData ))
976982
977983 // Parse the schema for use in ProcessInputPaths
978984 if doc , parseErr := openapi3 .NewLoader ().LoadFromData (schemaData ); parseErr == nil {
979985 r .doc = doc
986+ log .Tracew ("successfully parsed openapi schema for ProcessInputPaths" )
987+ } else {
988+ log .Errorw ("failed to parse openapi schema" , "error" , parseErr )
980989 }
990+ } else {
991+ log .Tracew ("failed to read openapi.json" , "error" , err )
981992 }
982993}
983994
0 commit comments