This is an automated email from the ASF dual-hosted git repository. SvenO3 pushed a commit to branch 4633-move-dataset-count-display-into-dataset-overview in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit f0fa876af3d488073f80935ab69143baf0095224 Author: Sven Oehler <[email protected]> AuthorDate: Wed Jun 24 15:07:08 2026 +0200 Update measurement count endpoint --- .../impl/datalake/DataLakeMeasureResource.java | 59 +++++++++++++++------- .../src/lib/apis/datalake-rest.service.ts | 16 +++--- .../datalake-configuration.component.ts | 38 +++++++------- 3 files changed, 68 insertions(+), 45 deletions(-) diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java index 57dfb7553e..166b3dd4be 100644 --- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java +++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/datalake/DataLakeMeasureResource.java @@ -29,9 +29,9 @@ import org.apache.streampipes.storage.api.explorer.IChartStorage; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PostFilter; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -44,7 +44,6 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; -import java.util.Map; import java.util.Objects; @RestController @@ -80,29 +79,53 @@ public class DataLakeMeasureResource extends AbstractDataLakeResource { } /** - * Handles HTTP GET requests to retrieve the entry counts of specified - * measurements. + * Handles HTTP GET requests to retrieve the entry count of a specified + * measurement. * - * @param measurementNames A list of measurement names to return the count. - * @return A ResponseEntity containing a map of measurement names and their - * corresponding entry counts. + * @param elementId The measurement id to return the count for. + * @return The entry count of the measurement. */ - @Operation(summary = "Retrieve measurement counts", description = "Retrieves the entry counts for the specified measurements from the data lake.") - @GetMapping(path = "/count", produces = MediaType.APPLICATION_JSON_VALUE) - @PreAuthorize("this.hasReadAuthority()") - @PostFilter("this.checkPermissionByName(filterObject.key, 'READ')") - public Map<String, Integer> getEntryCountsOfMeasurements( - @Parameter(description = "A list of measurement names to return the count.") @RequestParam(value = "measurementNames") List<String> measurementNames, - @Parameter(description = "The number of days from today where the count should start") @RequestParam(value = "daysBack", defaultValue = "-1") int daysBack) { + @Operation( + summary = "Retrieve measurement count", + description = "Retrieves the entry count for the specified measurement from the data lake." + ) + @GetMapping(path = "{id}/count", produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("this.hasReadAuthority() and hasPermission(#elementId, 'READ')") + public ResponseEntity<?> getEntryCountOfMeasurement( + @Parameter(description = "The measurement id to return the count for.") + @PathVariable("id") String elementId, + @Parameter(description = "The number of days from today where the count should start") + @RequestParam(value = "daysBack", defaultValue = "-1") int daysBack) { + var measure = this.dataLakeMeasureManagement.getById(elementId); + if (Objects.isNull(measure)) { + return notFound(); + } + var allMeasurements = this.dataLakeMeasureManagement.getAllMeasurements(); - var result = new DataExplorerDispatcher() + return ok(new DataExplorerDispatcher() .getDataExplorerManager() .getMeasurementCounter( allMeasurements, - measurementNames, + List.of(measure.getMeasureName()), daysBack) - .countMeasurementSizes(); - return result; + .countMeasurementSizes() + .getOrDefault(measure.getMeasureName(), 0)); + } + + @Operation( + summary = "Deprecated measurement count endpoint", + description = "Use /api/v4/datalake/measure/{id}/count instead.", + deprecated = true + ) + @GetMapping(path = "/count", produces = MediaType.APPLICATION_JSON_VALUE) + @PreAuthorize("this.hasReadAuthority()") + public ResponseEntity<?> getDeprecatedEntryCountOfMeasurement() { + return ResponseEntity + .status(HttpStatus.GONE) + .body(SpLogMessage.warn( + "Deprecated endpoint", + "Use /api/v4/datalake/measure/{id}/count instead." + )); } @GetMapping(path = "{id}", produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts index fb2ccafeff..8ab764a7ea 100644 --- a/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts +++ b/ui/projects/streampipes/platform-services/src/lib/apis/datalake-rest.service.ts @@ -64,18 +64,18 @@ export class DatalakeRestService { return this.baseUrl + '/api/v4/datalake/import'; } - getMeasurementEntryCounts( - measurementNames: string[], + getMeasurementEntryCount( + measurementId: string, daysBack = -1, - ): Observable<Record<string, number>> { - return this.http - .get(`${this.dataLakeMeasureUrl}/count`, { + ): Observable<number> { + return this.http.get<number>( + `${this.dataLakeMeasureUrl}/${encodeURIComponent(measurementId)}/count`, + { params: { - measurementNames, daysBack, }, - }) - .pipe(map(r => r as Record<string, number>)); + }, + ); } getAllMeasurementSeries(): Observable<DataLakeMeasure[]> { diff --git a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts index cf53cd6441..b98ac2278a 100644 --- a/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts +++ b/ui/src/app/dataset/components/datalake-configuration/datalake-configuration.component.ts @@ -91,7 +91,7 @@ import { MatProgressSpinner } from '@angular/material/progress-spinner'; import { DatePipe, DecimalPipe, NgStyle } from '@angular/common'; import { StyleDirective } from '@ngbracket/ngx-layout/extended'; import { MatMenuItem } from '@angular/material/menu'; -import { Subscription } from 'rxjs'; +import { forkJoin, Subscription } from 'rxjs'; @Component({ selector: 'sp-datalake-configuration', @@ -436,7 +436,7 @@ export class DatalakeConfigurationComponent } receiveTotalMeasurementSize(entry: DataLakeConfigurationEntry): void { - this.queryEntryCounts([entry.name], 'eventsTotal'); + this.queryEntryCounts([entry], 'eventsTotal'); } receiveMeasurementSizes(pageIndex: number): void { @@ -444,8 +444,7 @@ export class DatalakeConfigurationComponent const end = start + this.pageSize; const measurements = this.filteredMeasurements .slice(start, end) - .filter(m => m.eventsLatest === -1) - .map(m => m.name); + .filter(m => m.eventsLatest === -1); if (measurements.length > 0) { this.queryEntryCounts(measurements, 'eventsLatest', 7); } @@ -489,33 +488,34 @@ export class DatalakeConfigurationComponent } queryEntryCounts( - measurements: string[], + measurements: DataLakeConfigurationEntry[], targetField: string, daysBack = -1, ): void { this.applyLoadingStatus(measurements, targetField, true); - this.datalakeRestService - .getMeasurementEntryCounts(measurements, daysBack) - .subscribe(res => { - this.applyLoadingStatus(measurements, targetField, false); - this.availableMeasurements.forEach(m => { - if (res[m.name] !== undefined) { - m[targetField] = res[m.name]; - } - }); + forkJoin( + measurements.map(measurement => + this.datalakeRestService.getMeasurementEntryCount( + measurement.elementId, + daysBack, + ), + ), + ).subscribe(res => { + this.applyLoadingStatus(measurements, targetField, false); + measurements.forEach((measurement, index) => { + measurement[targetField] = res[index]; }); + }); } applyLoadingStatus( - measurements: string[], + measurements: DataLakeConfigurationEntry[], targetField: string, status: boolean, ): void { const loadingField = targetField + 'Loading'; - this.availableMeasurements.forEach(m => { - if (measurements.includes(m.name)) { - m[loadingField] = status; - } + measurements.forEach(measurement => { + measurement[loadingField] = status; }); }
