All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.ytsaurus.client.operations.CommandSpec Maven / Gradle / Ivy

The newest version!
package tech.ytsaurus.client.operations;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import tech.ytsaurus.client.TransactionalClient;
import tech.ytsaurus.core.DataSize;
import tech.ytsaurus.core.YtFormat;
import tech.ytsaurus.core.cypress.YPath;
import tech.ytsaurus.lang.NonNullApi;
import tech.ytsaurus.lang.NonNullFields;
import tech.ytsaurus.ysontree.YTreeBuilder;
import tech.ytsaurus.ysontree.YTreeStringNode;


/**
 * Immutable command spec.
 */
@NonNullFields
@NonNullApi
public class CommandSpec implements Spec, UserJobSpec {
    private final String command;

    private final YTreeStringNode inputFormat;

    private final YTreeStringNode outputFormat;

    private final List files;

    @Nullable
    private final DataSize memoryLimit;

    private final boolean useTmpfs;

    @Nullable
    private final DataSize tmpfsSize;

    private final Map environment;
    @Nullable
    private final Double cpuLimit;

    @Nullable
    private final Long jobTimeLimit;

    // Only relevant for vanilla operations
    // (TODO: move to separate class VanillaCommandSpec)
    protected final List outputTablePaths;
    private final @Nullable
    Integer jobCount;

    /**
     * Create command spec from command with other options set to defaults.
     */
    public CommandSpec(String command) {
        this(builder().setCommand(command));
    }

    protected > CommandSpec(BuilderBase builder) {
        if (builder.command == null) {
            throw new RuntimeException("command is not set");
        }
        command = builder.command;
        files = builder.files;
        memoryLimit = builder.memoryLimit;
        useTmpfs = builder.useTmpfs;
        tmpfsSize = builder.tmpfsSize;
        environment = builder.environment;
        cpuLimit = builder.cpuLimit;
        jobTimeLimit = builder.jobTimeLimit;
        jobCount = builder.jobCount;
        outputTablePaths = builder.outputTablePaths;

        var formatContext = FormatContext.builder()
                .setOutputTableCount(outputTablePaths.size())
                .build();
        inputFormat = builder.inputType != null
                ? builder.inputType.format(formatContext)
                : builder.inputFormat;
        outputFormat = builder.outputType != null
                ? builder.outputType.format(formatContext)
                : builder.outputFormat;
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        CommandSpec spec = (CommandSpec) obj;
        return command.equals(spec.command)
                && inputFormat.equals(spec.inputFormat)
                && outputFormat.equals(spec.outputFormat)
                && files.equals(spec.files)
                && Optional.ofNullable(memoryLimit).equals(Optional.ofNullable(spec.memoryLimit))
                && useTmpfs == spec.useTmpfs
                && Optional.ofNullable(tmpfsSize).equals(Optional.ofNullable(spec.tmpfsSize))
                && environment.equals(spec.environment)
                && Optional.ofNullable(cpuLimit).equals(Optional.ofNullable(spec.cpuLimit))
                && Optional.ofNullable(jobTimeLimit).equals(Optional.ofNullable(spec.jobTimeLimit))
                && outputTablePaths.equals(spec.outputTablePaths)
                && Optional.ofNullable(jobCount).equals(Optional.ofNullable(spec.jobCount));
    }

    /**
     * @see Builder#setCommand(String)
     */
    public String getCommand() {
        return command;
    }

    /**
     * @see Builder#setInputFormat(YTreeStringNode)
     */
    public YTreeStringNode getInputFormat() {
        return inputFormat;
    }

    /**
     * @see Builder#setOutputFormat(YTreeStringNode)
     */
    public YTreeStringNode getOutputFormat() {
        return outputFormat;
    }

    /**
     * @see Builder#setFiles(List)
     */
    public List getFiles() {
        return files;
    }

    /**
     * @see Builder#setMemoryLimit(DataSize)
     */
    public Optional getMemoryLimit() {
        return Optional.ofNullable(memoryLimit);
    }

    public boolean isUseTmpfs() {
        return useTmpfs;
    }

    public Optional getTmpfsSize() {
        return Optional.ofNullable(tmpfsSize);
    }

    /**
     * @see Builder#setEnvironment(Map)
     */
    public Map getEnvironment() {
        return environment;
    }

    /**
     * @see Builder#setCpuLimit(Double)
     */
    public Optional getCpuLimit() {
        return Optional.ofNullable(cpuLimit);
    }

    /**
     * @see Builder#setJobTimeLimit(Long)
     */
    @SuppressWarnings("unused")
    public Optional getJobTimeLimit() {
        return Optional.ofNullable(jobTimeLimit);
    }

    /**
     * @see Builder#setJobCount(Integer)
     */
    public Optional getJobCount() {
        return Optional.ofNullable(jobCount);
    }

    /**
     * Convert to yson.
     */
    @Override
    public YTreeBuilder prepare(YTreeBuilder builder, TransactionalClient yt,
                                SpecPreparationContext specPreparationContext) {
        return builder.beginMap()
                .key("command").value(command)
                .key("input_format").value(inputFormat)
                .key("output_format").value(outputFormat)
                .when(!files.isEmpty(), b -> b.key("file_paths").value(files, (b2, t) -> t.toTree(b2)))
                .when(memoryLimit != null, b -> b.key("memory_limit").value(memoryLimit.toBytes()))
                .when(useTmpfs, b -> b.key("tmpfs_path").value(".").key("copy_files").value(true))
                .when(tmpfsSize != null, b -> b.key("tmpfs_size").value(tmpfsSize.toBytes()))
                .key("environment").value(environment)
                .when(cpuLimit != null, b -> b.key("cpu_limit").value(cpuLimit))
                .when(jobTimeLimit != null, b -> b.key("job_time_limit").value(jobTimeLimit))
                .when(jobCount != null, b -> b.key("job_count").value(jobCount))
                .when(!outputTablePaths.isEmpty(), b -> b.key("output_table_paths").value(
                        outputTablePaths.stream().map(YPath::toTree).collect(Collectors.toList())
                ))
                .endMap();
    }

    /**
     * Convert to yson.
     */
    @Override
    public YTreeBuilder prepare(
            YTreeBuilder builder, TransactionalClient yt, SpecPreparationContext specPreparationContext,
            FormatContext formatContext) {
        return prepare(builder, yt, specPreparationContext);
    }

    /**
     * Create empty builder.
     */
    public static BuilderBase builder() {
        return new Builder();
    }

    /**
     * Builder of {@link CommandSpec}.
     */
    protected static class Builder extends BuilderBase {
        @Override
        protected Builder self() {
            return this;
        }
    }

    // BuilderBase was taken out because there is another client
    // which we need to support too and which use the same CommandSpec class.
    @NonNullFields
    @NonNullApi
    public abstract static class BuilderBase> {
        @Nullable
        String command = null;
        YTreeStringNode inputFormat = YtFormat.YSON_BINARY;
        YTreeStringNode outputFormat = YtFormat.YSON_BINARY;
        @Nullable
        YTableEntryType inputType;
        @Nullable
        YTableEntryType outputType;
        List files = new ArrayList<>();
        @Nullable
        DataSize memoryLimit = null;
        boolean useTmpfs = false;
        @Nullable
        DataSize tmpfsSize = null;
        Map environment = new HashMap<>();
        @Nullable
        Double cpuLimit = null;
        @Nullable
        Long jobTimeLimit = null;
        @Nullable
        Integer jobCount = null;
        List outputTablePaths = new ArrayList<>();

        public CommandSpec build() {
            return new CommandSpec(this);
        }

        /**
         * Set command.
         */
        public T setCommand(String command) {
            this.command = command;
            return self();
        }

        /**
         * Set format of input data.
         */
        public T setInputFormat(YTreeStringNode inputFormat) {
            this.inputFormat = inputFormat;
            return self();
        }

        /**
         * Set format of output data.
         */
        public T setOutputFormat(YTreeStringNode outputFormat) {
            this.outputFormat = outputFormat;
            return self();
        }

        /**
         * Set input type for resolve format of input data.
         * Format resolved with this input type overrides {@link #inputFormat}.
         */
        public T setInputType(@Nullable YTableEntryType inputType) {
            this.inputType = inputType;
            return self();
        }

        /**
         * Set output type for resolve format of output data.
         * Format resolved with this output type overrides {@link #outputFormat}.
         */
        public T setOutputType(@Nullable YTableEntryType outputType) {
            this.outputType = outputType;
            return self();
        }

        /**
         * Set files which should be available inside job.
         */
        public T setFiles(List files) {
            this.files = files;
            return self();
        }

        /**
         * Set memoryLimit which specifies how much memory job process can use.
         */
        public T setMemoryLimit(@Nullable DataSize memoryLimit) {
            this.memoryLimit = memoryLimit;
            return self();
        }

        public T setUseTmpfs(boolean useTmpfs) {
            this.useTmpfs = useTmpfs;
            return self();
        }

        public T setTmpfsSize(@Nullable DataSize tmpfsSize) {
            this.tmpfsSize = tmpfsSize;
            return self();
        }

        /**
         * Set a dictionary of environment variables that will be specified during the operation.
         */
        public T setEnvironment(Map environment) {
            this.environment = environment;
            return self();
        }

        /**
         * Set maximum number of CPU cores for a single job to use.
         */
        public T setCpuLimit(@Nullable Double cpuLimit) {
            this.cpuLimit = cpuLimit;
            return self();
        }

        /**
         * Set limit on job execution time.
         * Jobs that exceed this limit will be considered failed.
         */
        public T setJobTimeLimit(@Nullable Long jobTimeLimit) {
            this.jobTimeLimit = jobTimeLimit;
            return self();
        }

        /**
         * Set how many jobs should be run, it is advisory.
         */
        public T setJobCount(@Nullable Integer jobCount) {
            this.jobCount = jobCount;
            return self();
        }

        /**
         * Set output table paths, only for vanilla operations.
         */
        public T setOutputTablePaths(List outputTablePaths) {
            this.outputTablePaths = outputTablePaths;
            return self();
        }

        protected abstract T self();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy