Skip to content

Commit 0914b92

Browse files
committed
fix: include module binaries in task hash
Signed-off-by: FloWuenne <flowuenne@gmail.com>
1 parent c70376d commit 0914b92

2 files changed

Lines changed: 71 additions & 1 deletion

File tree

modules/nextflow/src/main/groovy/nextflow/processor/TaskHasher.groovy

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package nextflow.processor
1717

1818
import java.nio.file.Path
19+
import java.nio.file.Files
1920

2021
import com.google.common.hash.HashCode
2122
import groovy.json.JsonOutput
@@ -215,13 +216,28 @@ class TaskHasher {
215216
final tokenizer = new StringTokenizer(script, " \t\n\r\f()[]{};&|<>`")
216217
while( tokenizer.hasMoreTokens() ) {
217218
final token = tokenizer.nextToken()
218-
final path = session.binEntries.get(token)
219+
final path = getBinEntry(token)
219220
if( path )
220221
result.add(path)
221222
}
222223
return result
223224
}
224225

226+
@Memoized
227+
protected Path getBinEntry(String name) {
228+
final fromProjectBin = session.binEntries.get(name)
229+
if( fromProjectBin )
230+
return fromProjectBin
231+
232+
for( final dir : processor.getBinDirs() ) {
233+
final candidate = dir.resolve(name)
234+
if( Files.isExecutable(candidate) )
235+
return candidate
236+
}
237+
238+
return null
239+
}
240+
225241
private String safeTaskName(TaskRun task) {
226242
return task != null ? task.lazyName() : task.processor.name
227243
}

modules/nextflow/src/test/groovy/nextflow/processor/TaskHasherTest.groovy

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,22 @@
1616

1717
package nextflow.processor
1818

19+
import java.nio.file.Files
1920
import java.nio.file.Path
2021

2122
import nextflow.Session
2223
import nextflow.script.ProcessConfig
2324
import spock.lang.Specification
25+
import spock.lang.TempDir
2426
/**
2527
*
2628
* @author Paolo Di Tommaso <paolo.ditommaso@gmail.com>
2729
*/
2830
class TaskHasherTest extends Specification {
2931

32+
@TempDir
33+
Path tempDir
34+
3035
def 'should compute unique task hash' () {
3136

3237
given:
@@ -94,6 +99,55 @@ class TaskHasherTest extends Specification {
9499
result.contains(Path.of('/some/path/bar.sh'))
95100
}
96101

102+
def 'should include referenced module bin files in the task hash' () {
103+
104+
given:
105+
def moduleBin = tempDir.resolve('resources/usr/bin')
106+
Files.createDirectories(moduleBin)
107+
def script = moduleBin.resolve('foo.sh')
108+
Files.writeString(script, 'echo first version\n')
109+
script.toFile().setExecutable(true)
110+
def session = Mock(Session) {
111+
getUniqueId() >> UUID.fromString('b69b6eeb-b332-4d2c-9957-c291b15f498c')
112+
getBinEntries() >> [:]
113+
}
114+
def config = Mock(ProcessConfig) {
115+
getHashMode() >> null
116+
}
117+
def processor = Mock(TaskProcessor) {
118+
getName() >> 'hello'
119+
getSession() >> session
120+
getConfig() >> config
121+
getBinDirs() >> [moduleBin]
122+
}
123+
def task = Mock(TaskRun) {
124+
getSource() >> 'foo.sh --version'
125+
isContainerEnabled() >> false
126+
getInputs() >> [:]
127+
getOutputEvals() >> null
128+
getConfig() >> Mock(TaskConfig) {
129+
getModule() >> null
130+
getStubBlock() >> null
131+
getArchitecture() >> null
132+
}
133+
getCondaEnv() >> null
134+
getSpackEnv() >> null
135+
getProcessor() >> processor
136+
}
137+
138+
when:
139+
def firstHash = Spy(TaskHasher, constructorArgs: [task]) {
140+
getTaskGlobalVars() >> [:]
141+
}.compute()
142+
Files.writeString(script, 'echo second version\n')
143+
def secondHash = Spy(TaskHasher, constructorArgs: [task]) {
144+
getTaskGlobalVars() >> [:]
145+
}.compute()
146+
147+
then:
148+
firstHash != secondHash
149+
}
150+
97151
def 'should get task directive vars' () {
98152
given:
99153
def processor = Spy(TaskProcessor) {

0 commit comments

Comments
 (0)