public Tuple getParentFolderId()

in services/library/src/main/java/com/google/cloud/pso/bq_snapshot_manager/services/scan/ResourceScannerImpl.java [150:206]


    public Tuple<String, String> getParentFolderId(String projectId, String runId) throws IOException {

        /**
         * Resource Manager API has a rate limit of 10 GET operations per second. This means that
         * looking up the folder for each table (for thousands of tables) is not scalable.
         * For that we use a cache layer to store the project-folder pairs in the scope of each run (to address cache invalidation)
         */

        // 1. Lookup the project in the cache

        // construct a key including the pro
        String keyStr = generateProjectFolderCacheKey(projectId, runId);

        Key projectFolderKey = datastore.newKeyFactory().setKind(DATASTORE_KIND).newKey(keyStr);
        Entity projectFolderEntity = datastore.get(projectFolderKey);

        if(projectFolderEntity == null){
            // 2.a project-folder entity doesn't exist in the cache

            // 2.a.1. Query the Resource Manager API
            String parentFolderFromApi = cloudResourceManager
                    .projects()
                    .get(String.format("projects/%s", projectId))
                    .execute()
                    .getParent();

            // API returns "folders/folder_name" and we just return folder_name
            String parentFolderFinal = parentFolderFromApi.startsWith("folders/")?
                    parentFolderFromApi.substring(8):
                    null;

            Timestamp now = Timestamp.now();
            // 2.a.2. Add it to the cache
            projectFolderEntity = Entity.newBuilder(projectFolderKey)
                    .set("project", projectId)
                    .set("parent_folder", parentFolderFinal)
                    .set("run_id", runId)
                    .set("updated_at", now)
                    .set("expires_at", Utils.addSeconds(now, Utils.SECONDS_IN_DAY)) // TTL 1 day
                    .build();

            datastore.put(projectFolderEntity);

            // 2.a.3 return it to the caller
            return Tuple.of(parentFolderFinal, PROJECT_FOLDER_LKP_SRC_API);
        }else{

            String projectFolderFromCache = projectFolderEntity
                    .getValue("parent_folder")
                    .get()
                    .toString();

            // project-folder entity exist in the cache
            // 2.b.1 Return from cache
            return Tuple.of(projectFolderFromCache, PROJECT_FOLDER_LKP_SRC_CACHE);
        }
    }