marklogic / ml-gradle

Gradle plugin for automating everything involving MarkLogic
Other
73 stars 77 forks source link

Delete a single trigger #245

Open hansenmc opened 7 years ago

hansenmc commented 7 years ago

An issue that we ran into is that over time we have accumulated triggers that may either be renamed or removed between deployments. We don't want to perform an mlClearTriggersDatabase, because we don't want transactions to occur without the triggers, and do not always want to take an outage if we have CPF and other application triggers that are needed and expected to be retained.

So, we created a custom task that will selectively delete triggers (by name) that are not currently in our source tree, and who's name doesn't start with "cpf:". That way, as triggers are removed from the project, or renamed, they get deleted as part of the next deployment.

It could be expanded to incorporate other patterns/prefixes for a "whitelist" to prevent them from being deleted, but figured that this might be a good starting point, if deemed useful and worth incorporating into ml-gradle.

import groovy.json.JsonSlurper
task mlDeleteLegacyTriggers(trype: com.marklogic.gradle.task.XccTask, group: "ml-gradle Trigger") {
  description = "Removes application Triggers that have been previously deployed, but are no longer included in the project"
  xccUrl = contentXccUrl
  doFirst {
    def currentTriggers = (file('src/main/ml-config/triggers')
      .listFiles()
      .findAll { it.name.endsWith('.json') }
      .collect{ new JsonSlurper().parseText(it.text)}
      .name).join(',')
    xquery = """
import module namespace trgr="http://marklogic.com/xdmp/triggers" at "/MarkLogic/triggers.xqy";
declare variable \$WHITELIST := tokenize("${currentTriggers}", ",");
xdmp:invoke-function(function(){
    collection("http://marklogic.com/xdmp/triggers")/trgr:trigger/trgr:trigger-name/fn:string()
      [not(starts-with(., 'cpf:')) and not (. = \$WHITELIST)] ! trgr:remove-trigger(.)
  },
  <option xmlns="xdmp:eval">
    <database>{xdmp:triggers-database()}</database>
    <transaction-mode>update-auto-commit</transaction-mode>
  </option>
}
    """
  }
}
mlDeployTriggers.dependsOn mlDeleteLegacyTriggers
rjrudin commented 7 years ago

I like this. I'm thinking I'd like to build it as Java code within ml-app-deployer, possibly even with ml-javaclient-util.

Seems like something similar could be done for the schemas database too?

hansenmc commented 7 years ago

Yes, would be great to have for other types of artifacts as well.

I would love to see ml-gradle become more “groovy”. It would be nice to at least have more of the tasks and dependencies configured in ml-grade, instead of ml-app-deployer or ml-javaclient-util for specific functions. It would make it easier to customize the behaviors (add/remove task dependencies, augment/replace task definitions, etc) that you would expect to be able to do in Gradle builds but are sometimes not able to with ml-gradle tasks.

rjrudin commented 7 years ago

That's a good point. The litmus test I've been using is - would someone want to execute this code outside the context of Gradle, with the Data Hub Framework being the main case for that litmus test. JUnit is another context.

dmcassel commented 6 years ago

would it make sense to offer a "gradle nukeTrigger -Ptrigger=foo" command? That could both remove it from the filesystem and from a triggers database.

rjrudin commented 5 years ago

I think just doing "mlDeleteTrigger -Ptrigger=foo" is the way to go for now. I think @hansenmc 's script is good for custom purposes, but I don't want a task in ml-gradle that could delete something from the triggers database that wasn't expected to be deleted. I'd rather just provide a shortcut for deleting a trigger.

Will re-title this and toss it into the next release.