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

Addressable data store (aka CID store) #5715

Draft
wants to merge 45 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
472fcc7
Addressable data store
pditommaso Jan 26, 2025
4f8c524
Merge branch 'master' into cid-store
pditommaso Jan 31, 2025
b5e8c46
Addressable data store [wip 2] [ci skip]
pditommaso Jan 31, 2025
669afd5
Minor changes [ci skip]
pditommaso Jan 31, 2025
c93a713
Addressable data store
pditommaso Jan 26, 2025
c0c660f
Addressable data store [wip 2] [ci skip]
pditommaso Jan 31, 2025
2a2d76f
Minor changes [ci skip]
pditommaso Jan 31, 2025
a2139e3
M0 implementation
jorgee Feb 12, 2025
fddc5f7
fix tests
jorgee Feb 12, 2025
fe780a8
fix tests
jorgee Feb 12, 2025
f9f7ed2
first M1 updates
jorgee Feb 14, 2025
0c2492e
fix tests
jorgee Feb 14, 2025
41ac817
update descriptions
jorgee Feb 17, 2025
cdc3116
fix test
jorgee Feb 17, 2025
642e7b1
Merge branch 'master' into cid-store-m0
pditommaso Feb 19, 2025
1400e80
Merge branch 'cid-store' of github.com:nextflow-io/nextflow into cid-…
pditommaso Feb 19, 2025
d64c71a
Merge branch 'master' into cid-store
pditommaso Feb 19, 2025
975143f
Merge branch 'cid-store' into cid-store-m0
pditommaso Feb 19, 2025
82b1ccd
First commit to M1 implementation
jorgee Feb 27, 2025
edfaf5b
fix NPE in tests
jorgee Feb 27, 2025
c207d92
Fix NPE in tests
jorgee Feb 27, 2025
f4b9031
Add CidStore factory
jorgee Feb 27, 2025
b89cdf1
fix cid paht hash validation
jorgee Feb 27, 2025
54849d3
Merge branch 'master' into cid-store
jorgee Feb 28, 2025
fdbda27
Merge branch 'cid-store' into cid-store-m0
jorgee Feb 28, 2025
84ee951
Merge branch 'master' into cid-store-m0
pditommaso Mar 1, 2025
0d1a74f
Merge pull request #5787 from nextflow-io/cid-store-m0 [ci fast]
pditommaso Mar 1, 2025
34cc0b1
Cleanup and formatting
pditommaso Mar 1, 2025
bd96bc8
Decouple cid store from session (#5833) [ci fast]
pditommaso Mar 3, 2025
4c0ef8f
Add cid command help
jorgee Mar 4, 2025
b9de3e6
Fix CID store errors when workflow outputs in s3
jorgee Mar 4, 2025
bebe947
Merge branch 'master' into cid-store
pditommaso Mar 6, 2025
36d293f
Merge branch 'master' into cid-store
pditommaso Mar 7, 2025
76f3494
Merge branch 'master' into cid-store
jorgee Mar 11, 2025
063a0ec
Decouple CID FileSystem from Local file system and other fixes (#5866)
jorgee Mar 11, 2025
acabc9c
Merge branch 'master' into cid-store
pditommaso Mar 11, 2025
3e2ca19
Just blank [ci skip]
pditommaso Mar 11, 2025
90c8e38
fix unexpected warning in cidpath hash validation
jorgee Mar 12, 2025
5276645
Refactor CID store as plugin (#5877)
pditommaso Mar 12, 2025
be2fefc
Merge with master@00a53b97 [ci fast]
pditommaso Mar 15, 2025
9de3b04
Merge branch 'master' into cid-store
pditommaso Mar 15, 2025
16f74b4
Restore unneeded changes [ci fast]
pditommaso Mar 15, 2025
eb14d4b
Add CID H2 plugin (#5889)
pditommaso Mar 20, 2025
c04a58f
Merge branch 'master' into cid-store
pditommaso Mar 21, 2025
db79c43
Add serde interfaces (#5893) [ci skip]
pditommaso Mar 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ task compile {

def getRuntimeConfigs() {
def names = subprojects
.findAll { prj -> prj.name in ['nextflow','nf-commons','nf-httpfs','nf-lang'] }
.findAll { prj -> prj.name in ['nextflow','nf-cid','nf-commons','nf-httpfs','nf-lang'] }
.collect { it.name }

FileCollection result = null
Expand All @@ -263,7 +263,7 @@ task exportClasspath {
def home = System.getProperty('user.home')
def all = getRuntimeConfigs()
def libs = all.collect { File file -> /*println file.canonicalPath.replace(home, '$HOME');*/ file.canonicalPath; }
['nextflow','nf-commons','nf-httpfs','nf-lang'].each {libs << file("modules/$it/build/libs/${it}-${version}.jar").canonicalPath }
['nextflow','nf-cid','nf-commons','nf-httpfs','nf-lang'].each {libs << file("modules/$it/build/libs/${it}-${version}.jar").canonicalPath }
file('.launch.classpath').text = libs.unique().join(':')
}
}
Expand All @@ -276,7 +276,7 @@ ext.nexusEmail = project.findProperty('nexusEmail')
// `signing.keyId` property needs to be defined in the `gradle.properties` file
ext.enableSignArchives = project.findProperty('signing.keyId')

ext.coreProjects = projects( ':nextflow', ':nf-commons', ':nf-httpfs', ':nf-lang' )
ext.coreProjects = projects( ':nextflow', ':nf-cid', ':nf-commons', ':nf-httpfs', ':nf-lang' )

configure(coreProjects) {
group = 'io.nextflow'
Expand Down
2 changes: 1 addition & 1 deletion modules/nextflow/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ dependencies {
api 'io.seqera:lib-trace:0.1.0'

testImplementation 'org.subethamail:subethasmtp:3.1.7'

testImplementation (project(':nf-cid'))
// test configuration
testFixturesApi ("org.apache.groovy:groovy-test:4.0.26") { exclude group: 'org.apache.groovy' }
testFixturesApi ("org.objenesis:objenesis:3.4")
Expand Down
231 changes: 231 additions & 0 deletions modules/nextflow/src/main/groovy/nextflow/cli/CmdCid.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*
* Copyright 2013-2025, Seqera Labs
*
* 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 nextflow.cli

import java.nio.file.Paths

import com.beust.jcommander.Parameter
import com.beust.jcommander.Parameters
import groovy.transform.CompileStatic
import nextflow.config.ConfigBuilder
import nextflow.config.ConfigMap
import nextflow.exception.AbortOperationException
import nextflow.plugin.Plugins
import org.pf4j.ExtensionPoint

/**
* CID command line interface
*
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
@CompileStatic
@Parameters(commandDescription = "Explore workflows CID metadata")
class CmdCid extends CmdBase implements UsageAware {

private static final String NAME = 'cid'

interface CidCommand extends ExtensionPoint {
void log(ConfigMap config)
void show(ConfigMap config, List<String> args)
void lineage(ConfigMap config, List<String> args)
}

interface SubCmd {
String getName()
String getDescription()
void apply(List<String> args)
void usage()
}

private List<SubCmd> commands = new ArrayList<>()

private CidCommand operation

private ConfigMap config

CmdCid() {
commands << new CmdLog()
commands << new CmdShow()
commands << new CmdLineage()
}

@Parameter(hidden = true)
List<String> args

@Override
String getName() {
return NAME
}

@Override
void run() {
if( !args ) {
return
}
// setup the plugins system and load the secrets provider
Plugins.init()
// load the config
this.config = new ConfigBuilder()
.setOptions(launcher.options)
.setBaseDir(Paths.get('.'))
.build()
// init plugins
Plugins.load(config)
// load the command operations
this.operation = Plugins.getExtension(CidCommand)
if( !operation )
throw new IllegalStateException("Unable to load CID plugin")
// consume the first argument
getCmd(args).apply(args.drop(1))
}

/**
* Print the command usage help
*/
void usage() {
usage(args)
}

/**
* Print the command usage help
*
* @param args The arguments as entered by the user
*/
void usage(List<String> args) {
if( !args ) {
List<String> result = []
result << this.getClass().getAnnotation(Parameters).commandDescription()
result << "Usage: nextflow $NAME <sub-command> [options]".toString()
result << ''
result << 'Commands:'
int len = 0
commands.forEach {len = it.name.size() > len ? it.name.size() : len }
commands.sort(){it.name}.each { result << " ${it.name.padRight(len)}\t${it.description}".toString() }
result << ''
println result.join('\n').toString()
}
else {
def sub = commands.find { it.name == args[0] }
if( sub )
sub.usage()
else {
throw new AbortOperationException("Unknown $NAME sub-command: ${args[0]}")
}
}
}

protected SubCmd getCmd(List<String> args) {

def cmd = commands.find { it.name == args[0] }
if( cmd ) {
return cmd
}

def matches = commands.collect{ it.name }.closest(args[0])
def msg = "Unknown cloud sub-command: ${args[0]}"
if( matches )
msg += " -- Did you mean one of these?\n" + matches.collect { " $it"}.join('\n')
throw new AbortOperationException(msg)
}

class CmdLog implements SubCmd {

@Override
String getName() {
return 'log'
}

@Override
String getDescription() {
return 'Print the CID execution log'
}

@Override
void apply(List<String> args) {
if (args.size() != 0) {
println("ERROR: Incorrect number of parameters")
usage()
return
}
operation.log(config)
}

@Override
void usage() {
println description
println "Usage: nextflow $NAME $name"
}
}

class CmdShow implements SubCmd{

@Override
String getName() {
return 'show'
}

@Override
String getDescription() {
return 'Print the description of a CID reference'
}

void apply(List<String> args) {
if (args.size() != 1) {
println("ERROR: Incorrect number of parameters")
usage()
return
}

operation.show(config, args)
}

@Override
void usage() {
println description
println "Usage: nextflow $NAME $name <CID reference> "
}
}

class CmdLineage implements SubCmd {

@Override
String getName() { 'lineage' }

@Override
String getDescription() {
return 'Render a lineage graph for a workflow output'
}

void apply(List<String> args) {
if (args.size() != 2) {
println("ERROR: Incorrect number of parameters")
usage()
return
}

operation.lineage(config, args)
}

@Override
void usage() {
println description
println "Usage: nextflow $NAME $name <workflow output CID> <html output file>"
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class Launcher {
new CmdHelp(),
new CmdSelfUpdate(),
new CmdPlugin(),
new CmdInspect()
new CmdInspect(),
new CmdCid()
]

if(SecretsLoader.isEnabled())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class MermaidHtmlRenderer implements DagRenderer {
file.text = template.replace('REPLACE_WITH_NETWORK_DATA', network)
}

private String readTemplate() {
static String readTemplate() {
final writer = new StringWriter()
final res = MermaidHtmlRenderer.class.getResourceAsStream('mermaid.dag.template.html')
int ch
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2013-2025, Seqera Labs
*
* 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 nextflow.file

import java.nio.file.LinkOption
import java.nio.file.Path

/**
* Marker interface for objects that represent a real path.
*
* This interface is used in the { @link nextflow.processor.TaskProcessor } when managing the foreign file staging.
*
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
*/
interface RealPathAware {
/**
* Returns the real path
* @param options
* @return
*/
Path toRealPath(LinkOption... options)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class TaskId extends Number implements Comparable, Serializable, Cloneable {

private final int value

int getValue() { value }

static TaskId of( value ) {
if( value instanceof Integer )
return new TaskId(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
*/
package nextflow.processor

import nextflow.trace.TraceRecord

import static nextflow.processor.ErrorStrategy.*

import java.lang.reflect.InvocationTargetException
Expand Down Expand Up @@ -80,6 +78,7 @@ import nextflow.file.FileHelper
import nextflow.file.FileHolder
import nextflow.file.FilePatternSplitter
import nextflow.file.FilePorter
import nextflow.file.RealPathAware
import nextflow.plugin.Plugins
import nextflow.processor.tip.TaskTipProvider
import nextflow.script.BaseScript
Expand All @@ -106,6 +105,7 @@ import nextflow.script.params.TupleInParam
import nextflow.script.params.TupleOutParam
import nextflow.script.params.ValueInParam
import nextflow.script.params.ValueOutParam
import nextflow.trace.TraceRecord
import nextflow.util.ArrayBag
import nextflow.util.BlankSeparatedList
import nextflow.util.CacheHelper
Expand Down Expand Up @@ -1939,6 +1939,9 @@ class TaskProcessor {

if( item instanceof Path || coerceToPath ) {
def path = normalizeToPath(item)
if (path instanceof RealPathAware){
path = path.toRealPath()
}
def target = executor.isForeignFile(path) ? batch.addToForeign(path) : path
def holder = new FileHolder(target)
files << holder
Expand Down Expand Up @@ -2274,7 +2277,7 @@ class TaskProcessor {
* @return The list of paths of scripts in the project bin folder referenced in the task command
*/
@Memoized
protected List<Path> getTaskBinEntries(String script) {
public List<Path> getTaskBinEntries(String script) {
List<Path> result = []
def tokenizer = new StringTokenizer(script," \t\n\r\f()[]{};&|<>`")
while( tokenizer.hasMoreTokens() ) {
Expand Down Expand Up @@ -2307,7 +2310,7 @@ class TaskProcessor {
log.info(buffer.toString())
}

protected Map<String,Object> getTaskGlobalVars(TaskRun task) {
public Map<String,Object> getTaskGlobalVars(TaskRun task) {
final result = task.getGlobalVars(ownerScript.binding)
final directives = getTaskExtensionDirectiveVars(task)
result.putAll(directives)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -990,5 +990,9 @@ class TaskRun implements Cloneable {
CondaConfig getCondaConfig() {
return processor.session.getCondaConfig()
}

String getStubSource(){
return config?.getStubBlock()?.source
}
}

Loading