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

com.dimajix.flowman.kernel.WorkspaceClient Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2023 The Flowman Authors
 *
 * 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.
 */

package com.dimajix.flowman.kernel;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;

import com.dimajix.flowman.kernel.proto.workspace.GetWorkspaceRequest;
import com.dimajix.shaded.guava.io.Files;
import com.dimajix.shaded.protobuf.ByteString;
import com.dimajix.shaded.grpc.ManagedChannel;
import lombok.val;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dimajix.flowman.kernel.proto.FileType;
import com.dimajix.flowman.kernel.proto.workspace.CleanWorkspaceRequest;
import com.dimajix.flowman.kernel.proto.workspace.UploadFilesRequest;
import com.dimajix.flowman.kernel.proto.workspace.WorkspaceServiceGrpc;
import com.dimajix.common.io.Globber;


public final class WorkspaceClient extends AbstractClient {
    private final Logger logger = LoggerFactory.getLogger(WorkspaceClient.class);
    private final ManagedChannel channel;
    private final WorkspaceServiceGrpc.WorkspaceServiceBlockingStub blockingStub;
    private final WorkspaceServiceGrpc.WorkspaceServiceStub asyncStub;
    private final String workspaceId;


    public WorkspaceClient(ManagedChannel channel, String workspaceId) {
        this.channel = channel;
        this.workspaceId = workspaceId;
        blockingStub = WorkspaceServiceGrpc.newBlockingStub(channel);
        asyncStub = WorkspaceServiceGrpc.newStub(channel);
    }

    @Override
    public boolean isShutdown() {
        return channel.isTerminated();
    }

    @Override
    public boolean isTerminated() {
        return channel.isTerminated();
    }

    public List listProjects() {
        val request = GetWorkspaceRequest.newBuilder()
            .setWorkspaceId(workspaceId)
            .build();
        val result = call(() -> blockingStub.getWorkspace(request));
        return result.getWorkspace().getProjectsList();
    }

    public String getWorkspaceId() { return workspaceId; }

    public void cleanWorkspace() {
        val request = CleanWorkspaceRequest.newBuilder()
            .setWorkspaceId(workspaceId)
            .build();
        call(() -> blockingStub.cleanWorkspace(request));
    }

    public void uploadWorkspace(File localDirectory) throws IOException {
        if (!localDirectory.exists())
            throw new IllegalArgumentException("Local workspace directory '" + localDirectory + "' does not exist");
        if (!localDirectory.isDirectory())
            throw new IllegalArgumentException("Local workspace '" + localDirectory + "' must be a directory, but it is not");

        val globber = new Globber(localDirectory);
        val rootPath = globber.getRootPath();
        logger.info("Uploading local directory '" + rootPath + "' to workspace '" + workspaceId + "'...");

        val maxMessageSize = 4194304;
        val iter = globber.glob()
            .map(file -> uploadFile(rootPath, file, maxMessageSize))
            .iterator();
        stream(asyncStub::uploadFiles, iter);
    }

    private UploadFilesRequest uploadFile(Path root, Path src, int maxMessageSize) {
        val filename = root.relativize(src).toString();
        val result = UploadFilesRequest.newBuilder()
                .setWorkspaceId(workspaceId)
                .setFileName(filename);

        val msgSize = result.build().toByteArray().length;
        val srcFile = src.toFile();
        if (srcFile.isDirectory()) {
            logger.info("Uploading directory'" + src + "' as '" + filename + "' to kernel...");
            result.setFileType(FileType.DIRECTORY);
        }
        else if (srcFile.isFile()) {
            logger.debug("Uploading file '" + src + "' as '" + filename + "' to kernel...");
            try {
                val fileSize = srcFile.length();
                if (fileSize + msgSize + 1024 > maxMessageSize) {
                    val msg = "File '" + src + "' is too big to transfer to Flowman kernel workspace, " + fileSize + " bytes. You can exclude files in .flowman-ignore";
                    logger.error(msg);
                    throw new IllegalArgumentException(msg);
                }
                val content = Files.toByteArray(srcFile);
                result.setFileType(FileType.FILE);
                result.setFileContent(ByteString.copyFrom(content));
            }
            catch(IOException ex) {
                throw new RuntimeException(ex);
            }
        }
        else {
            logger.info("Ignoring special file'" + src + "'...");
        }
        return result.build();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy