Files
Jungfraujoch/broker/JFJochBrokerHttp.h
T
leonarski_f 84228bf8be
Build Packages / Create release (push) Successful in 24s
Build Packages / build:viewer:macos-arm64:nocuda (push) Successful in 3m29s
Build Packages / build:rugnux:macos-arm64:nocuda (push) Successful in 2m43s
Build Packages / build:rugnux:linux-aarch64:cuda (push) Successful in 8m27s
Build Packages / build:rugnux:linux-x86_64:cuda (push) Successful in 9m53s
Build Packages / build:viewer:linux-x86_64:nocuda (push) Successful in 9m58s
Build Packages / build:viewer:linux-x86_64:cuda (push) Successful in 11m22s
Build Packages / build:jfjoch:rocky8:nocuda (push) Successful in 13m39s
Build Packages / build:viewer:windows-x86_64:nocuda (push) Successful in 18m37s
Build Packages / build:jfjoch:rocky9:nocuda (push) Successful in 16m32s
Build Packages / build:viewer:windows-x86_64:cuda (push) Successful in 24m11s
Build Packages / HDF5 consumer tests (DIALS, XDS) (push) Successful in 25m30s
Build Packages / build:jfjoch:ubuntu2404:nocuda (push) Successful in 19m3s
Build Packages / build:jfjoch:ubuntu2204:nocuda (push) Successful in 20m23s
Build Packages / build:jfjoch:rocky8:cuda-sls9 (push) Successful in 19m41s
Build Packages / Generate python client (push) Successful in 50s
Build Packages / Build documentation (push) Successful in 1m16s
Build Packages / build:jfjoch:rocky9:cuda-sls9 (push) Successful in 21m0s
Build Packages / build:jfjoch:rocky8:cuda (push) Successful in 18m38s
Build Packages / build:rugnux:windows-x86_64:cuda (push) Successful in 14m33s
Build Packages / build:jfjoch:rocky9:cuda (push) Successful in 17m55s
Build Packages / build:jfjoch:ubuntu2204:cuda (push) Successful in 20m50s
Build Packages / build:jfjoch:ubuntu2404:cuda (push) Successful in 18m38s
Build Packages / Unit tests (push) Successful in 1h46m14s
v1.0.0-rc.173 (#83)
* jfjoch_broker: Optional per-dataset authentication - statistics, images and plots can require a bearer token, which jfjoch_viewer supports.
* jfjoch_viewer: Dark mode and a theme-matched colour scheme, a magnifier panel, and simpler contrast and background controls.
* Rugnux: Multiple performance improvements on GPU and CPU (CPU-only processing up to 40% faster, faster image decoding on ARM), with unchanged results.
* Rugnux: `--model` rigid-body refinement runs on the GPU, and the model-validation check is faster and more reliable.
* Rugnux: Improved scaling and merging - error model, outlier rejection, absorption correction and French-Wilson amplitudes now agree more closely with XDS and ctruncate.
* Rugnux: Improved integration - radial background on powder and ice rings, crowded rotation data keep their reflections, and CPU-only builds integrate large unit cells as GPU builds do.
* Rugnux: More robust detector geometry - measured beam centre, X-ray bandwidth and goniometer rate, and geometry refinement accepted only on significant evidence.
* Rugnux: Merged files are written in the standard setting, or in the setting of a reference MTZ, structure-factor mmCIF or model, with its free-R flags.
* Rugnux: Richer report - ice and powder rings, further lattices, superstructure candidates and mosaicity, with warnings worded as prompts to check.
* Rugnux: Clear error messages when a data set needs more GPU or host memory than is available.

Reviewed-on: #83
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-09-29 15:57:32 +02:00

218 lines
11 KiB
C++

// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
// Using OpenAPI licensed with Apache License 2.0
#pragma once
#include <httplib.h>
#include <nlohmann/json.hpp>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "../common/Logger.h"
#include "JFJochServices.h"
#include "JFJochStateMachine.h"
#include "OpenAPIConvert.h"
#include "gen/model/Azim_int_settings.h"
#include "gen/model/Bragg_integration_settings.h"
#include "gen/model/Broker_status.h"
#include "gen/model/Dark_mask_settings.h"
#include "gen/model/Dataset_settings.h"
#include "gen/model/Detector_selection.h"
#include "gen/model/Detector_settings.h"
#include "gen/model/Detector_status.h"
#include "gen/model/Error_message.h"
#include "gen/model/File_writer_settings.h"
#include "gen/model/Image_buffer_status.h"
#include "gen/model/Image_format_settings.h"
#include "gen/model/Image_pusher_status.h"
#include "gen/model/Indexing_settings.h"
#include "gen/model/Instrument_metadata.h"
#include "gen/model/Jfjoch_statistics.h"
#include "gen/model/Plots.h"
#include "gen/model/Roi_definitions.h"
#include "gen/model/Scan_result.h"
#include "gen/model/Spot_finding_settings.h"
#include "gen/model/Zeromq_metadata_settings.h"
#include "gen/model/Zeromq_preview_settings.h"
class JFJochBrokerHttp {
Logger logger{"JFJochBroker"};
JFJochServices services{logger};
JFJochStateMachine state_machine;
std::string frontend_directory;
// The API declares 400 as a plain-text exception string and 500 as an error_message object,
// so an error response has to carry the content type its body actually is - a JSON body
// labelled text/plain is what the generated clients refuse to deserialize.
struct HttpError {
int code;
std::string body;
const char *content_type;
};
static void send_error(httplib::Response &res, const HttpError &error) {
res.status = error.code;
res.set_content(error.body, error.content_type);
}
static std::string error_message_json(const std::string &msg, const std::string &reason);
template<class T>
void ProcessOutput(const T &output, httplib::Response &response) {
std::stringstream s;
if (!output.validate(s)) {
logger.Error(s.str());
send_error(response, {500, error_message_json(s.str(), "Other"), "application/json"});
return;
}
nlohmann::json j = output;
response.status = 200;
response.set_content(j.dump(), "application/json");
}
// Writes the 401 and returns false when the current dataset is protected and the request did
// not present one of its tokens. The response says nothing about the dataset.
bool Authorized(const httplib::Request &req, httplib::Response &res) const;
static std::optional<std::string> AuthorizationHeader(const httplib::Request &req);
HttpError handleParsingException(const std::exception &ex) const noexcept;
HttpError handleOperationException(const std::exception &ex) const noexcept;
void register_routes(httplib::Server &server);
void cancel_post(httplib::Response &response);
void deactivate_post(httplib::Response &response);
void initialize_post(httplib::Response &response);
void start_post(const org::openapitools::server::model::Dataset_settings &datasetSettings,
httplib::Response &response);
void status_get(httplib::Response &response);
void wait_till_done_post(const std::optional<int32_t> &timeout, httplib::Response &response);
void wait_until_running_post(const std::optional<int32_t> &timeout, httplib::Response &response);
void trigger_post(httplib::Response &response);
void pedestal_post(httplib::Response &response);
void config_detector_get(httplib::Response &response);
void config_detector_put(const org::openapitools::server::model::Detector_settings &detectorSettings,
httplib::Response &response);
void config_azim_int_get(httplib::Response &response);
void config_azim_int_put(const org::openapitools::server::model::Azim_int_settings &azimIntSettings,
httplib::Response &response);
void config_select_detector_get(httplib::Response &response);
void config_select_detector_put(const org::openapitools::server::model::Detector_selection &detectorSelection,
httplib::Response &response);
void config_spot_finding_get(httplib::Response &response);
void config_spot_finding_put(const org::openapitools::server::model::Spot_finding_settings &spotFindingSettings,
httplib::Response &response);
void statistics_calibration_get(httplib::Response &response);
void statistics_data_collection_get(httplib::Response &response);
void config_file_writer_get(httplib::Response &response);
void config_file_writer_put(const org::openapitools::server::model::File_writer_settings &fileWriterSettings,
httplib::Response &response);
void config_image_format_get(httplib::Response &response);
void config_image_format_put(const org::openapitools::server::model::Image_format_settings &imageFormatSettings,
httplib::Response &response);
void config_image_format_conversion_post(httplib::Response &response);
void config_image_format_raw_post(httplib::Response &response);
void fpga_status_get(httplib::Response &response);
void statistics_get(const httplib::Request &request, httplib::Response &response);
void config_zeromq_preview_get(httplib::Response &response);
void config_zeromq_preview_put(const org::openapitools::server::model::Zeromq_preview_settings &zeromqPreviewSettings,
httplib::Response &response);
void config_zeromq_metadata_get(httplib::Response &response);
void config_zeromq_metadata_put(const org::openapitools::server::model::Zeromq_metadata_settings &zeromqMetadataSettings,
httplib::Response &response);
void config_internal_generator_image_put(const std::optional<int64_t> &id,
const httplib::Request &request,
httplib::Response &response);
void config_internal_generator_image_tiff_put(const std::optional<int64_t> &id,
const httplib::Request &request,
httplib::Response &response);
void image_buffer_clear_post(httplib::Response &response);
void image_buffer_image_cbor_get(const std::optional<int64_t> &id, httplib::Response &response);
void image_buffer_image_jpeg_get(const std::optional<int64_t> &id, const std::optional<bool> &showUserMask,
const std::optional<bool> &showRoi, const std::optional<bool> &showSpots,
const std::optional<bool> &showPredictions,
const std::optional<bool> &showBeamCenter, const std::optional<float> &saturation,
const std::optional<int64_t> &jpegQuality, const std::optional<float> &showResRing,
const std::optional<std::string> &color, const std::optional<bool> &showResEst,
httplib::Response &response);
void image_buffer_image_tiff_get(const std::optional<int64_t> &id, httplib::Response &response);
void image_buffer_start_cbor_get(httplib::Response &response);
void image_buffer_status_get(httplib::Response &response);
void detector_status_get(httplib::Response &response);
void image_pusher_status_get(httplib::Response &response);
void preview_pedestal_tiff_get(const std::optional<int32_t> &gainLevel, const std::optional<int32_t> &sc,
httplib::Response &response);
void preview_plot_bin_get(const std::optional<std::string> &type, const std::optional<std::string> &roi,
httplib::Response &response);
void preview_plot_get(const std::optional<std::string> &type, const std::optional<int32_t> &binning,
const std::optional<float> &fill,
const std::optional<bool> &experimentalCoord, const std::optional<std::string> &azintUnit,
httplib::Response &response);
void config_mask_get(httplib::Response &response);
void config_mask_tiff_get(httplib::Response &response);
void config_user_mask_get(httplib::Response &response);
void config_user_mask_put(const httplib::Request &request, httplib::Response &response);
void config_user_mask_tiff_get(httplib::Response &response);
void config_user_mask_tiff_put(const httplib::Request &request, httplib::Response &response);
void config_roi_get(httplib::Response &response);
void config_roi_put(const org::openapitools::server::model::Roi_definitions &roiDefinitions,
httplib::Response &response);
void result_scan_get(httplib::Response &response);
void version_get(httplib::Response &response);
void config_instrument_get(httplib::Response &response);
void config_instrument_put(const org::openapitools::server::model::Instrument_metadata &instrumentMetadata,
httplib::Response &response);
void config_indexing_get(httplib::Response &response);
void config_indexing_put(const org::openapitools::server::model::Indexing_settings &indexingSettings,
httplib::Response &response);
void config_bragg_integration_get(httplib::Response &response);
void config_bragg_integration_put(const org::openapitools::server::model::Bragg_integration_settings &braggIntegrationSettings,
httplib::Response &response);
void config_dark_mask_get(httplib::Response &response);
void config_dark_mask_put(const org::openapitools::server::model::Dark_mask_settings &darkMaskSettings,
httplib::Response &response);
void xfel_event_code_get(httplib::Response &response);
void xfel_pulse_id_get(httplib::Response &response);
public:
JFJochBrokerHttp(const DiffractionExperiment &experiment,
const SpotFindingSettings &spot_finding_settings);
void AddDetectorSetup(const DetectorSetup &setup);
JFJochServices &Services();
JFJochBrokerHttp &FrontendDirectory(const std::string &directory);
void attach(httplib::Server &server);
~JFJochBrokerHttp() = default;
};