public void serveResource()

in genie-web/src/main/java/com/netflix/genie/web/services/impl/JobDirectoryServerServiceImpl.java [147:246]


    public void serveResource(
        final String id,
        final URL baseUrl,
        final String relativePath,
        final HttpServletRequest request,
        final HttpServletResponse response
    ) throws GenieException {
        final long start = System.nanoTime();
        final Set<Tag> tags = Sets.newHashSet();
        try {
            // Normalize the base url. Make sure it ends in /.
            final URI baseUri = new URI(baseUrl.toString() + SLASH).normalize();

            // Lookup archive status and job execution type
            final ArchiveStatus archiveStatus = this.persistenceService.getJobArchiveStatus(id);
            tags.add(Tag.of(ARCHIVE_STATUS_TAG, archiveStatus.name()));

            final DirectoryManifest manifest;
            final URI jobDirRoot;

            switch (archiveStatus) {
                case NO_FILES:
                    // Job failed before any files were created. Nothing to serve.
                    throw new GenieNotFoundException("Job failed before any file was created: " + id);

                case FAILED:
                    // Archive failed (also implies job is done). Return 404 without further processing
                    throw new GenieNotFoundException("Job failed to archive files: " + id);

                case DISABLED:
                    // Not a possible state in database as of now [GENIE-657]
                    throw new GeniePreconditionException("Archive disabled for job " + id);

                case UNKNOWN:
                    // Set by the server when an agent is AWOL long enough.
                    // Archive status is truly unknown. As of now, fall-through and attempt serving from archive.

                case ARCHIVED:
                    // Serve file from archive
                    log.debug("Routing request to archive");
                    final ArchivedJobMetadata archivedJobMetadata = this.archivedJobService.getArchivedJobMetadata(id);
                    final String rangeHeader = request.getHeader(HttpHeaders.RANGE);
                    manifest = archivedJobMetadata.getManifest();
                    final URI baseJobDirRoot = archivedJobMetadata.getArchiveBaseUri();
                    jobDirRoot = new URIBuilder(baseJobDirRoot).setFragment(rangeHeader).build();
                    break;

                case PENDING:
                    log.debug("Routing request to connected agent");
                    if (!this.agentRoutingService.isAgentConnectionLocal(id)) {
                        throw new GenieServerUnavailableException("Agent connection has moved or was terminated");
                    }
                    manifest = this.agentFileStreamService.getManifest(id).orElseThrow(
                        () -> new GenieServerUnavailableException("Manifest not found for job " + id)
                    );
                    jobDirRoot = AgentFileProtocolResolver.createUri(
                        id,
                        SLASH,
                        request.getHeader(HttpHeaders.RANGE)
                    );
                    break;

                default:
                    throw new GenieServerException("Unknown archive status " + archiveStatus + "(" + id + ")");
            }

            log.debug(
                "Serving file: {} for job: {} (archive status: {})",
                relativePath,
                id,
                archiveStatus
            );

            // Common handling of archived, locally running v3 job or locally connected v4 job
            this.handleRequest(baseUri, relativePath, request, response, manifest, jobDirRoot);
            MetricsUtils.addSuccessTags(tags);

        } catch (NotFoundException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw new GenieNotFoundException(e.getMessage(), e);
        } catch (IOException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw new GenieServerException("Error serving response: " + e.getMessage(), e);
        } catch (URISyntaxException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw new GenieServerException(e.getMessage(), e);
        } catch (final JobNotArchivedException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw new GeniePreconditionException("Job outputs were not archived", e);
        } catch (final JobNotFoundException | JobDirectoryManifestNotFoundException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw new GenieNotFoundException("Failed to retrieve job archived files metadata", e);
        } catch (GenieException e) {
            MetricsUtils.addFailureTagsWithException(tags, e);
            throw e;
        } finally {
            final long elapsed = System.nanoTime() - start;
            this.meterRegistry.timer(SERVE_RESOURCE_TIMER, tags).record(elapsed, TimeUnit.NANOSECONDS);
        }
    }