Skip to content

Commit 3f8569f

Browse files
cmdcolinclaude
andcommitted
Fix deleteOrganismFeatures: add @transactional, flush deletes, use consistent organism lookup
- Add @transactional to deleteOrganismFeatures controller action (was inheriting readOnly=true from class, which could prevent writes in Grails 7) - Use preferenceService.getOrganismForTokenInDB for organism lookup (handles both numeric IDs and common names consistently, matching other controller actions) - Add flush:true to Feature.delete() and FeatureEvent.delete() calls in service - Fix response.status set after render in error handler - Add debug logging for delete operations - Increase CI log output for delete diagnostics Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 97b34e9 commit 3f8569f

3 files changed

Lines changed: 18 additions & 15 deletions

File tree

.github/workflows/python-apollo.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,8 @@ jobs:
128128
- name: Print Apollo log on failure
129129
if: failure()
130130
run: |
131+
echo "=== Delete-related log lines ==="
132+
grep -iE 'deleteOrganism|features to delete|Deleted.*features|problem removing|not authorized to delete' apollo.log | tail -50 || true
133+
echo ""
131134
echo "=== Last 500 lines of Apollo log ==="
132135
tail -500 apollo.log

grails-app/controllers/org/bbop/apollo/OrganismController.groovy

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ class OrganismController {
167167
render responseObject as JSON
168168
}
169169

170+
@Transactional
170171
def deleteOrganismFeatures() {
171172
JSONObject organismJson = permissionService.handleInput(request, params)
172173
try {
@@ -181,11 +182,7 @@ class OrganismController {
181182
return
182183
}
183184

184-
Organism organism = Organism.findByCommonName(organismJson.organism)
185-
186-
if (!organism) {
187-
organism = Organism.findById(organismJson.organism)
188-
}
185+
Organism organism = preferenceService.getOrganismForTokenInDB(organismJson.organism as String)
189186

190187
if (!organism) {
191188
throw new Exception("Can not find organism for ${organismJson.organism} to remove features of")
@@ -194,18 +191,20 @@ class OrganismController {
194191
if (organismJson.sequences) {
195192
List<String> sequenceNames = organismJson.sequences.toString().split(",")
196193
List<Sequence> sequences = Sequence.findAllByOrganismAndNameInList(organism, sequenceNames)
197-
organismService.deleteAllFeaturesForSequences(sequences)
194+
int deleted = organismService.deleteAllFeaturesForSequences(sequences)
195+
log.info "Deleted ${deleted} features for sequences ${sequenceNames} of organism ${organism.commonName}"
198196
} else {
199-
organismService.deleteAllFeaturesForOrganism(organism)
197+
int deleted = organismService.deleteAllFeaturesForOrganism(organism)
198+
log.info "Deleted ${deleted} features for organism ${organism.commonName}"
200199
}
201200

202201
render [:] as JSON
203202
}
204203
catch (Exception e) {
205204
def error = [error: 'problem removing organism features for organism: ' + e]
206-
render error as JSON
207-
response.status = HttpStatus.INTERNAL_SERVER_ERROR.value()
208205
log.error(error.error, e)
206+
response.status = HttpStatus.INTERNAL_SERVER_ERROR.value()
207+
render error as JSON
209208
}
210209
}
211210

grails-app/services/org/bbop/apollo/OrganismService.groovy

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,13 @@ class OrganismService {
7171
log.debug "uniqueNames ${uniqueNames.size()}"
7272
Feature.withNewTransaction{
7373
def features = Feature.findAllByIdInList(ids)
74+
log.debug "Found ${features.size()} features for deletion"
7475
for (f in features) {
75-
f.delete()
76+
f.delete(flush: true)
7677
}
7778
def featureEvents = FeatureEvent.findAllByUniqueNameInList(uniqueNames)
7879
for (fe in featureEvents) {
79-
fe.delete()
80+
fe.delete(flush: true)
8081
}
8182
count += featureList.size()
8283
log.info "${count} / ${featurePairs.size()} = ${100 * count / featurePairs.size()}% "
@@ -102,7 +103,7 @@ class OrganismService {
102103
int totalDeleted = 0
103104
log.debug "organism ${organism}"
104105
def featureCount = Feature.executeQuery("select count(f) from Feature f join f.featureLocations fl join fl.sequence s join s.organism o where o=:organism", [organism: organism])[0]
105-
log.debug "features to delete ${featureCount}"
106+
log.info "features to delete ${featureCount} for organism ${organism.commonName}"
106107
while(featureCount>0){
107108
def featurePairs = Feature.executeQuery("select f.id,f.uniqueName from Feature f join f.featureLocations fl join fl.sequence s join s.organism o where o=:organism", [max:MAX_DELETE_SIZE,organism: organism])
108109
// maximum transaction size 30
@@ -127,14 +128,14 @@ class OrganismService {
127128
log.debug "uniqueNames ${uniqueNames.size()}"
128129
Feature.withNewTransaction{
129130
def features = Feature.findAllByIdInList(ids)
131+
log.debug "Found ${features.size()} features for deletion"
130132
for (f in features) {
131-
f.delete()
133+
f.delete(flush: true)
132134
}
133135
def featureEvents = FeatureEvent.findAllByUniqueNameInList(uniqueNames)
134136
for (fe in featureEvents) {
135-
fe.delete()
137+
fe.delete(flush: true)
136138
}
137-
organism.save(flush: true)
138139
count += featureList.size()
139140
log.info "${count} / ${featurePairs.size()} = ${100 * count / featurePairs.size()}% "
140141
}

0 commit comments

Comments
 (0)