Skip to content

Commit 5d15ed8

Browse files
authored
new rename command (#11)
closes #10 Signed-off-by: Jorge Aguilera <jorge@incsteps.com>
1 parent a5e9bc0 commit 5d15ed8

File tree

13 files changed

+294
-31
lines changed

13 files changed

+294
-31
lines changed

src/docs/asciidoc/index.adoc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ INFO:: By the moment, to close the web server you need to send a kill signal (or
4444
image::screenshot1.png[]
4545

4646
.execution tasks list
47+
4748
image::screenshot2.png[]
4849

4950
.task detail
@@ -76,4 +77,22 @@ time use nf-cachebrowser
7677
== Postgres Storage (TODO!!)
7778

7879
In the same way as DuckDB database, we're working in a plugin to use Postgres as cache. nf-cachebrowser will allow
79-
inspect this storage
80+
inspect this storage
81+
82+
== Rename Workdir
83+
84+
You can rewrite the storage changing the `workdir` to a new path using the `rename` command.
85+
86+
This can be useful in case you want to move the storage to a new location, for example.
87+
88+
The command:
89+
90+
`nextflow plugin nf-cachebrowser:rename /current/path /new/path/to/use`
91+
92+
will replace in all tasks with `workdir` as `/current/path` to `/new/path/to/use`
93+
94+
Also, You can specify to apply the rename only to a task:
95+
96+
`nextflow plugin nf-cachebrowser:rename --task helloWorld /current/path /new/path/to/use`
97+
98+

src/main/groovy/com/incsteps/nextflow/cachebrowser/Plugin.groovy

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.incsteps.nextflow.cachebrowser
1818

1919

20-
import com.incsteps.nextflow.cachebrowser.mn.WebServer
2120
import groovy.transform.CompileStatic
2221
import groovy.util.logging.Slf4j
2322
import nextflow.cli.PluginAbstractExec
@@ -44,13 +43,14 @@ class Plugin extends BasePlugin implements PluginAbstractExec{
4443

4544
@Override
4645
List<String> getCommands() {
47-
return ['run']
46+
return ['run', 'rename']
4847
}
4948

5049
@Override
5150
int exec(String cmd, List<String> args) {
5251
return switch (cmd){
5352
case 'run'-> run(args)
53+
case 'rename'-> rename(args)
5454
default -> -1
5555
}
5656
}
@@ -65,4 +65,14 @@ class Plugin extends BasePlugin implements PluginAbstractExec{
6565
}
6666
}
6767

68+
int rename(List<String> args){
69+
try {
70+
RenameWorkdirCmd.run(args,wrapper.pluginClassLoader)
71+
0
72+
}catch(Throwable t){
73+
log.error("Error running rename workdir command",t)
74+
-1
75+
}
76+
}
77+
6878
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.incsteps.nextflow.cachebrowser
2+
import com.beust.jcommander.Parameter
3+
import com.beust.jcommander.Parameters
4+
import groovy.transform.CompileStatic
5+
6+
@Parameters(optionPrefixes = "--")
7+
@CompileStatic
8+
class RenameConfig {
9+
10+
@Parameter(names = '--help', description='help', help=true)
11+
boolean help
12+
13+
@Parameter(names = '--directory', description='nextflow directory')
14+
String workdir = ''
15+
16+
@Parameter(names = '--duckdb', description='a jdbc url to duckdb')
17+
String duckdbJdbc = ''
18+
19+
@Parameter(names = '--postgres', description='a jdbc url to postgres')
20+
String postgresJdbc = ''
21+
22+
@Parameter(names = '--task', description='replace in specified task')
23+
String task
24+
25+
@Parameter(description = 'new path to use', required = true)
26+
List<String> args
27+
28+
29+
String[] toMicronautProperties(){
30+
adjustWorkDir()
31+
def map = [
32+
"--micronaut.server.port" : "-1" // random port
33+
]
34+
map.putAll([
35+
"--storage": "local", // by default
36+
"--storage.dir" : workdir
37+
])
38+
if( duckdbJdbc.length() ){
39+
map.putAll([
40+
"--storage": "duckdb",
41+
"--duckdb.jdbc" : duckdbJdbc
42+
])
43+
}
44+
map.entrySet().collect{ "$it.key=$it.value".toString()} as String[]
45+
}
46+
47+
private void adjustWorkDir(){
48+
if( workdir?.length() == 0 && System.getenv("NXF_CACHE_DIR")){
49+
workdir = System.getenv("NXF_CACHE_DIR")
50+
}
51+
}
52+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.incsteps.nextflow.cachebrowser
2+
3+
4+
import com.beust.jcommander.JCommander
5+
import com.beust.jcommander.ParameterException
6+
import com.incsteps.nextflow.cachebrowser.mn.StorageService
7+
import groovy.transform.CompileStatic
8+
import groovy.util.logging.Slf4j
9+
import io.micronaut.runtime.Micronaut
10+
import jakarta.inject.Singleton
11+
12+
@Slf4j
13+
@CompileStatic
14+
@Singleton
15+
class RenameWorkdirCmd {
16+
17+
RenameWorkdirCmd(){
18+
}
19+
20+
static void run(List<String>args, ClassLoader classLoader) {
21+
RenameConfig config = new RenameConfig()
22+
23+
try {
24+
JCommander jc = new JCommander()
25+
jc.addObject(config)
26+
jc.parse(args as String[])
27+
28+
if (config.help) {
29+
jc.usage()
30+
return
31+
}
32+
33+
if( config.args.size() != 2){
34+
throw new ParameterException("oldPath newPath are required")
35+
}
36+
}catch (e){
37+
System.err.println(e.toString())
38+
return
39+
}
40+
41+
run( config, classLoader )
42+
}
43+
44+
static void run(RenameConfig config, ClassLoader classLoader) {
45+
46+
def mn = Micronaut.build(config.toMicronautProperties())
47+
.classLoader(classLoader)
48+
.mainClass(RenameWorkdirCmd)
49+
.start()
50+
51+
def storage = mn.getBean(StorageService)
52+
53+
storage.renameWorkDir(config.args.first, config.args.last, config.task)
54+
55+
mn.stop()
56+
}
57+
58+
static void main(String[]args){
59+
System.setProperty("micronaut.environments","dev")
60+
run( args as List<String>, RenameWorkdirCmd.classLoader )
61+
}
62+
}

src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/WebServer.groovy renamed to src/main/groovy/com/incsteps/nextflow/cachebrowser/WebServer.groovy

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
package com.incsteps.nextflow.cachebrowser.mn
1+
package com.incsteps.nextflow.cachebrowser
2+
23

3-
import ch.qos.logback.classic.util.ContextInitializer
44
import com.beust.jcommander.JCommander
55
import groovy.transform.CompileStatic
66
import groovy.util.logging.Slf4j
@@ -35,23 +35,25 @@ class WebServer {
3535
static void run(List<String>args, ClassLoader classLoader) {
3636
WebServerConfig config = new WebServerConfig()
3737

38-
JCommander jc = new JCommander()
39-
//jc.programName =" nf-cachebrowser"
40-
jc.addObject(config)
41-
jc.parse( args as String[])
38+
try {
39+
JCommander jc = new JCommander()
40+
//jc.programName =" nf-cachebrowser"
41+
jc.addObject(config)
42+
jc.parse(args as String[])
4243

43-
if( config.help ){
44-
jc.usage()
45-
return
44+
if (config.help) {
45+
jc.usage()
46+
return
47+
}
48+
}catch (e){
49+
System.err.println(e)
4650
}
4751

4852
run( config, classLoader )
4953
}
5054

5155
static void run(WebServerConfig config, ClassLoader classLoader) {
5256

53-
54-
5557
def mn = Micronaut.build(config.toMicronautProperties())
5658
.classLoader(classLoader)
5759
.mainClass(WebServer)

src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/WebServerConfig.groovy renamed to src/main/groovy/com/incsteps/nextflow/cachebrowser/WebServerConfig.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.incsteps.nextflow.cachebrowser.mn
1+
package com.incsteps.nextflow.cachebrowser
22
import com.beust.jcommander.Parameter
33
import com.beust.jcommander.Parameters
44
import groovy.transform.CompileStatic

src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/StorageService.groovy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ interface StorageService {
88
List<Execution> executions()
99

1010
List<TaskDetail> tasks(String session)
11+
12+
void renameWorkDir(String oldPath, String newPath, String task)
1113
}

src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/controller/ApiController.groovy

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package com.incsteps.nextflow.cachebrowser.mn.controller
33
import com.incsteps.nextflow.cachebrowser.mn.StorageService
44
import com.incsteps.nextflow.cachebrowser.mn.model.Execution
55
import com.incsteps.nextflow.cachebrowser.mn.model.TaskDetail
6+
import io.micronaut.http.annotation.Body
67
import io.micronaut.http.annotation.Controller
78
import io.micronaut.http.annotation.Get
9+
import io.micronaut.http.annotation.Put
810

911
@Controller("/api")
1012
class ApiController {
@@ -24,4 +26,10 @@ class ApiController {
2426
List<TaskDetail> tasks(String session){
2527
storageService.tasks(session)
2628
}
29+
30+
@Put("/executions/workdir")
31+
List<Execution>renameWorkDir(@Body RenameRequest renameRequest){
32+
storageService.renameWorkDir(renameRequest.oldPath(), renameRequest.newPath(), renameRequest.task())
33+
executions()
34+
}
2735
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.incsteps.nextflow.cachebrowser.mn.controller;
2+
3+
import io.micronaut.serde.annotation.Serdeable;
4+
5+
@Serdeable
6+
public record RenameRequest(
7+
String oldPath,
8+
String newPath,
9+
String task
10+
) {
11+
}

src/main/groovy/com/incsteps/nextflow/cachebrowser/mn/storages/AbstractStorage.groovy

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ package com.incsteps.nextflow.cachebrowser.mn.storages
22

33

44
import com.incsteps.nextflow.cachebrowser.mn.StorageService
5+
import com.incsteps.nextflow.cachebrowser.mn.model.Execution
56
import com.incsteps.nextflow.cachebrowser.mn.model.History
7+
import com.incsteps.nextflow.cachebrowser.mn.model.TaskDetail
8+
import groovy.util.logging.Slf4j
69

710
import java.nio.file.Paths
811

12+
@Slf4j
913
abstract class AbstractStorage implements StorageService{
1014

1115
private final String nextflowDir
@@ -14,11 +18,58 @@ abstract class AbstractStorage implements StorageService{
1418
this.nextflowDir = nextflowDir
1519
}
1620

21+
final List<Execution> executions(){
22+
executionsImpl()
23+
}
24+
25+
final List<TaskDetail> tasks(String session){
26+
tasksImpl(session)
27+
}
28+
29+
final void renameWorkDir(String oldPath, String newPath, String task){
30+
renameWorkDir0(oldPath, newPath, task)
31+
}
32+
33+
private void renameWorkDir0(String oldPath, String newPath, String task){
34+
newPath = newPath.endsWith("/") ? newPath : "$newPath/"
35+
def executions = executions()
36+
executions.each {execution->
37+
def session = execution.session
38+
def details = tasks(session)
39+
details.each{ detail ->
40+
if( !detail.trace.containsKey('workdir') ){
41+
return
42+
}
43+
if( !detail.trace.containsKey('hash') ){
44+
return
45+
}
46+
if( !detail.trace['workdir'].toString().startsWith(oldPath) ){
47+
return
48+
}
49+
if( task && detail.name != task){
50+
return
51+
}
52+
String current = detail.trace['workdir']
53+
String hash = detail.trace['hash']
54+
String base = newPath
55+
base += current.substring(current.indexOf(hash))
56+
detail.trace['workdir'] = base
57+
}
58+
saveTasks(session, details)
59+
}
60+
}
61+
62+
protected abstract List<Execution> executionsImpl()
63+
64+
protected abstract List<TaskDetail> tasksImpl(String session)
65+
66+
protected abstract void saveTasks(String session, List<TaskDetail>tasks)
67+
1768
protected String getNextflowDir(){
1869
nextflowDir
1970
}
2071

21-
List<History>historyList(){
72+
protected List<History>historyList(){
2273
def history = Paths.get(nextflowDir, ".nextflow", "history").toFile()
2374
if( !history.exists() && !history.isFile()) {
2475
throw new IllegalArgumentException("Missing .nextflow/history file")

0 commit comments

Comments
 (0)