Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NXP-29815: add an endpoint to recompute video renditions #4500

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -21,6 +21,8 @@

import static org.apache.commons.lang3.StringUtils.defaultIfBlank;

import java.time.Duration;

import org.nuxeo.common.xmap.annotation.XNode;
import org.nuxeo.common.xmap.annotation.XObject;
import org.nuxeo.common.xmap.registry.XEnable;
Expand All @@ -39,6 +41,9 @@ public class BulkActionDescriptor {

protected static final String DEFAULT_BATCH_SIZE = "25";

// @since 11.5
protected static final String DEFAULT_BATCH_TRANSACTION_TIMEOUT = "0s";

// @since 11.1
@XNode(value = XEnable.ENABLE, fallback = "@enabled")
@XEnable
Expand All @@ -58,6 +63,9 @@ public class BulkActionDescriptor {
@XNode(value = "@batchSize", defaultAssignment = DEFAULT_BATCH_SIZE)
public Integer batchSize;

@XNode(value = "@batchTransactionTimeout", defaultAssignment = DEFAULT_BATCH_TRANSACTION_TIMEOUT)
public Duration batchTransactionTimeout;

@XNode("@httpEnabled")
public Boolean httpEnabled = Boolean.FALSE;

Expand Down Expand Up @@ -87,6 +95,11 @@ public Integer getBatchSize() {
return batchSize;
}

// @since 11.5
public Duration getBatchTransactionTimeout() {
return batchTransactionTimeout;
}

// @since 11.4
public Long getDefaultQueryLimit() {
return defaultQueryLimit;
Expand Down Expand Up @@ -122,5 +135,4 @@ public String getDefaultScroller() {
public String getInputStream() {
return defaultIfBlank(inputStream, name);
}

}
Expand Up @@ -18,6 +18,7 @@
*/
package org.nuxeo.ecm.core.bulk;

import java.time.Duration;
import java.util.List;

/**
Expand All @@ -39,6 +40,13 @@ public interface BulkAdminService {

int getBatchSize(String action);

/**
* Returns the transaction timeout to use to process a batch.
*
* @since 11.5
*/
Duration getBatchTransactionTimeout(String action);

/**
* Returns the default query limit for the bulk action.
*
Expand Down
Expand Up @@ -98,6 +98,11 @@ public int getBatchSize(String action) {
return descriptors.get(action).getBatchSize();
}

@Override
public Duration getBatchTransactionTimeout(String action) {
return descriptors.get(action).getBatchTransactionTimeout();
}

@Override
public Long getQueryLimit(String action) {
return descriptors.get(action).getDefaultQueryLimit();
Expand Down
Expand Up @@ -141,6 +141,9 @@ public String submit(BulkCommand command) {
command.setBatchSize(adminService.getBatchSize(command.getAction()));
}
}
if (Duration.ZERO.equals(command.getBatchTransactionTimeout())) {
command.setBatchTransactionTimeout(adminService.getBatchTransactionTimeout(command.getAction()));
}
if (command.getQueryLimit() == null) {
command.setQueryLimit(adminService.getQueryLimit(command.getAction()));
}
Expand Down
Expand Up @@ -18,10 +18,12 @@
*/
package org.nuxeo.ecm.core.bulk.action.computation;

import static java.util.Objects.requireNonNullElse;
import static org.nuxeo.ecm.core.api.security.SecurityConstants.SYSTEM_USERNAME;
import static org.nuxeo.ecm.core.bulk.message.BulkStatus.State.ABORTED;

import java.io.Serializable;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -133,7 +135,10 @@ protected void processBatchOfDocuments(List<String> batch) {
if (batch == null || batch.isEmpty()) {
return;
}
TransactionHelper.runInTransaction(() -> {
int timeout = (int) requireNonNullElse(getBatchTransactionTimeout(), Duration.ZERO).toSeconds();
log.debug("The computation: {} is about to start a transaction with timeout: {}s to process the batch: {}",
metadata::name, () -> timeout, () -> batch);
TransactionHelper.runInTransaction(timeout, () -> {
try {
String username = command.getUsername();
String repository = command.getRepository();
Expand All @@ -147,6 +152,13 @@ protected void processBatchOfDocuments(List<String> batch) {
});
}

/**
* @return the transaction timeout to use to process the bucket, &lt;= 0 for the default
*/
protected Duration getBatchTransactionTimeout() {
return command.getBatchTransactionTimeout();
}

protected NuxeoLoginContext loginSystemOrUser(String username) throws LoginException {
return SYSTEM_USERNAME.equals(username) ? Framework.loginSystem() : Framework.loginUser(username);
}
Expand Down
Expand Up @@ -18,9 +18,11 @@
*/
package org.nuxeo.ecm.core.bulk.message;

import static java.util.Objects.requireNonNullElse;
import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.io.Serializable;
import java.time.Duration;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -62,6 +64,10 @@ public class BulkCommand implements Serializable {

protected int batchSize;

// @since 11.5
@Nullable
protected Long batchTransactionTimeout;

// @since 11.1
@Nullable
protected String scroller;
Expand Down Expand Up @@ -90,6 +96,7 @@ public BulkCommand(Builder builder) {
this.action = builder.action;
this.bucketSize = builder.bucketSize;
this.batchSize = builder.batchSize;
this.batchTransactionTimeout = builder.batchTransactionTimeout;
this.params = builder.params;
this.scroller = builder.scroller;
this.genericScroller = BooleanUtils.toBoolean(builder.genericScroller);
Expand Down Expand Up @@ -155,6 +162,15 @@ public int getBatchSize() {
return batchSize;
}

/**
* Precision is second.
*
* @since 11.5
*/
public Duration getBatchTransactionTimeout() {
return Duration.ofSeconds(requireNonNullElse(batchTransactionTimeout, 0L));
}

/**
* When greater than 0, the limit applied to the query results
*
Expand Down Expand Up @@ -191,6 +207,15 @@ public void setBucketSize(int bucketSize) {
this.bucketSize = bucketSize;
}

/**
* Precision is second.
*
* @since 11.5
*/
public void setBatchTransactionTimeout(Duration timeout) {
this.batchTransactionTimeout = timeout.toSeconds();
}

public void setRepository(String repository) {
this.repository = repository;
}
Expand All @@ -214,6 +239,8 @@ public static class Builder {

protected int batchSize;

protected Long batchTransactionTimeout;

protected String scroller;

protected Boolean genericScroller;
Expand Down Expand Up @@ -338,6 +365,16 @@ public Builder batch(int size) {
return this;
}

/**
* Precision is second.
*
* @since 11.5
*/
public Builder batchTransactionTimeout(Duration timeout) {
this.batchTransactionTimeout = timeout.toSeconds();
return this;
}

/**
* Add an action parameter
*/
Expand Down
2 changes: 1 addition & 1 deletion modules/platform/pom.xml
Expand Up @@ -85,7 +85,7 @@
<module>nuxeo-platform-userworkspace</module>
<module>nuxeo-platform-versioning-api</module>
<module>nuxeo-platform-versioning-core</module>
<module>nuxeo-platform-video</module>
<module>video</module>
<module>nuxeo-platform-virtualnavigation-core-contrib</module>
<module>nuxeo-platform-web-common</module>
<module>nuxeo-platform-webapp-types</module>
Expand Down
35 changes: 35 additions & 0 deletions modules/platform/video/nuxeo-platform-video-rest/pom.xml
@@ -0,0 +1,35 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-platform-video-parent</artifactId>
<version>11.5-SNAPSHOT</version>
</parent>

<artifactId>nuxeo-platform-video-rest</artifactId>
<name>Nuxeo Platform Video REST</name>
<description>Management API endpoint used to recompute video renditions</description>

<dependencies>
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-platform-video</artifactId>
</dependency>
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-rest-api-server</artifactId>
</dependency>
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-platform-video</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-rest-api-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,80 @@
/*
* (C) Copyright 2021 Nuxeo (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Charles Boidot
*/
package org.nuxeo.ecm.restapi.server.jaxrs.management;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.nuxeo.ecm.core.api.security.SecurityConstants.SYSTEM_USERNAME;
import static org.nuxeo.ecm.platform.video.computation.RecomputeTranscodedVideosComputation.PARAM_CONVERSION_NAMES;
import static org.nuxeo.ecm.platform.video.computation.RecomputeTranscodedVideosComputation.PARAM_XPATH;
import static org.nuxeo.ecm.platform.video.computation.RecomputeVideoInfoComputation.RECOMPUTE_ALL_VIDEO_INFO;

import java.io.Serializable;
import java.util.List;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.nuxeo.ecm.core.bulk.BulkService;
import org.nuxeo.ecm.core.bulk.message.BulkCommand;
import org.nuxeo.ecm.core.bulk.message.BulkStatus;
import org.nuxeo.ecm.platform.video.action.RecomputeVideoConversionsAction;
import org.nuxeo.ecm.webengine.model.WebObject;
import org.nuxeo.ecm.webengine.model.impl.AbstractResource;
import org.nuxeo.ecm.webengine.model.impl.ResourceTypeImpl;
import org.nuxeo.runtime.api.Framework;

/**
* @since 11.5
*/
@WebObject(type = ManagementObject.MANAGEMENT_OBJECT_PREFIX + "videos")
@Produces(APPLICATION_JSON)
public class VideosObject extends AbstractResource<ResourceTypeImpl> {

// By default we only recompute renditions for document without any renditions
public static final String VIDEOS_DEFAULT_QUERY = "SELECT * FROM Document WHERE ecm:mixinType = 'Video' AND ecm:isProxy = 0 AND ecm:isVersion = 0 AND vid:transcodedVideos/0/name IS NULL";

/**
* Recomputes video renditions for the documents matching the given query or {@link #VIDEOS_DEFAULT_QUERY} if not
* provided.
*
* @param query a custom query to specify which videos should be processed
* @return the {@link BulkStatus} of the command
*/
@POST
@Path("recompute")
public BulkStatus doPostVideos(@FormParam("query") String query,
@FormParam("conversionNames") List<String> conversionNames,
@FormParam("recomputeAllVideoInfo") Boolean recomputeAllVideoInfo) {
String finalQuery = StringUtils.defaultIfBlank(query, VIDEOS_DEFAULT_QUERY);
Boolean finalRecomputeAllVideoInfo = BooleanUtils.toBooleanDefaultIfNull(recomputeAllVideoInfo, false);
BulkService bulkService = Framework.getService(BulkService.class);
String commandId = bulkService.submit(new BulkCommand.Builder(RecomputeVideoConversionsAction.ACTION_NAME,
finalQuery, SYSTEM_USERNAME).repository(ctx.getCoreSession().getRepositoryName())
.param(PARAM_XPATH, "file:content")
.param(RECOMPUTE_ALL_VIDEO_INFO, finalRecomputeAllVideoInfo)
.param(PARAM_CONVERSION_NAMES, (Serializable) conversionNames)
.build());
return bulkService.getStatus(commandId);
}

}
@@ -0,0 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 1
Bundle-Name: Nuxeo Video REST
Bundle-SymbolicName: org.nuxeo.ecm.platform.video.rest;singleton:=true
Fragment-Host: org.nuxeo.ecm.platform.restapi.server
Bundle-Vendor: Nuxeo
Bundle-Version: 1.0.0