@@ -171,6 +171,58 @@ export async function getJobsListing(
171171 }
172172}
173173
174+ /**
175+ * Get a message explaining the change in size from the input to the output
176+ *
177+ * @param sizes - original and output sizes of the input in MiB (1024 x 1024 bytes)
178+ * @param precision - the number of decimal places to allow in the output
179+ * @returns a message explaining the size change as a percentage
180+ */
181+ export function sizeChangeMessage (
182+ sizes : { originalSize : number ; outputSize : number ; } ,
183+ precision : number = 2 ) : string {
184+ if ( sizes . originalSize === 0 ) {
185+ return 'Original size is 0 - percent size change N/A' ;
186+ }
187+ if ( sizes . outputSize === 0 ) {
188+ return 'Output size is 0 - percent size change N/A' ;
189+ }
190+ let result : string ;
191+ const diff = sizes . originalSize - sizes . outputSize ;
192+ if ( diff < 0 ) {
193+ const percent = ( - diff / sizes . originalSize * 100.0 ) . toFixed ( precision ) ;
194+ result = `${ percent } % increase` ;
195+ } else if ( diff > 0 ) {
196+ let percent = ( diff / sizes . originalSize * 100.0 ) . toFixed ( precision ) ;
197+ // due to JS precision issues, big changes will appear to be 100% reduction, which is impossible
198+ if ( percent === 100.0 . toFixed ( precision ) ) percent = 99.99 . toFixed ( precision ) ;
199+
200+ result = `${ percent } % reduction` ;
201+ } else {
202+ result = 'no change' ;
203+ }
204+
205+ return result ;
206+ }
207+
208+ /**
209+ * Format a data size number as a string for human presentation
210+ * @param mibSize - the float size in MiB (1024x1024 bytes)
211+ * @param precision - the number of decimal places to allow in the output
212+ * @returns a string representing the size using B, KiB, MiB, etc., notation
213+ */
214+ export function formatDataSize ( mibSize : number , precision : number = 2 ) : string {
215+ const units = [ 'B' , 'KiB' , 'MiB' , 'GiB' , 'TiB' , 'PiB' ] ;
216+ let size = mibSize * 1024 * 1024 ;
217+ let unitIndex = 0 ;
218+ while ( size >= 1024 && unitIndex < units . length - 1 ) {
219+ size /= 1024 ;
220+ unitIndex ++ ;
221+ }
222+
223+ return `${ size . toFixed ( precision ) } ${ units [ unitIndex ] } ` ;
224+ }
225+
174226/**
175227 * Express.js handler that returns job status for a single job `(/jobs/{jobID})`
176228 *
@@ -189,17 +241,11 @@ export async function getJobStatus(
189241 try {
190242 validateJobId ( jobID ) ;
191243 const { page, limit } = getPagingParams ( req , env . defaultResultPageSize ) ;
192- let job : Job ;
193- let pagination ;
194- let messages : JobMessage [ ] ;
195-
196- await db . transaction ( async ( tx ) => {
197- ( { job, pagination } = await Job . byJobID ( tx , jobID , true , true , false , page , limit ) ) ;
198- messages = await getMessagesForJob ( tx , jobID ) ;
199- } ) ;
244+ const { job, pagination } = await Job . byJobID ( db , jobID , true , true , false , page , limit ) ;
200245 if ( ! job ) {
201246 throw new NotFoundError ( `Unable to find job ${ jobID } ` ) ;
202247 }
248+ const messages : JobMessage [ ] = await getMessagesForJob ( db , jobID ) ;
203249 const isAdmin = await isAdminUser ( req ) ;
204250 const isAdminOrOwner = job . belongsToOrIsAdmin ( req . user , isAdmin ) ;
205251 const isJobShareable = await job . isShareable ( req . accessToken ) ;
@@ -210,6 +256,12 @@ export async function getJobStatus(
210256 const pagingLinks = getPagingLinks ( req , pagination ) . map ( ( link ) => new JobLink ( link ) ) ;
211257 job . links = job . links . concat ( pagingLinks ) ;
212258 const jobForDisplay = getJobForDisplay ( job , urlRoot , linkType , messages ) ;
259+ if ( job . original_data_size && job . output_data_size ) {
260+ jobForDisplay . originalDataSize = formatDataSize ( job . original_data_size ) ;
261+ jobForDisplay . outputDataSize = formatDataSize ( job . output_data_size ) ;
262+ jobForDisplay . dataSizePercentChange =
263+ sizeChangeMessage ( { originalSize : job . original_data_size , outputSize : job . output_data_size } ) ;
264+ }
213265 res . send ( jobForDisplay ) ;
214266 } catch ( e ) {
215267 req . context . logger . error ( e ) ;
0 commit comments