Skip to content

Commit

Permalink
fix(transaction): ensure transactions occur in correct context/thread
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Apr 23, 2024
1 parent 5baa88c commit aff1c63
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 131 deletions.
6 changes: 1 addition & 5 deletions src/main/java/io/cryostat/expressions/MatchExpressions.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Response;
Expand Down Expand Up @@ -73,10 +72,7 @@ public Multi<Map<String, Object>> list() {
@RolesAllowed("read")
@Blocking
public MatchedExpression get(@RestPath long id) throws ScriptException {
MatchExpression expr = MatchExpression.findById(id);
if (expr == null) {
throw new NotFoundException();
}
MatchExpression expr = MatchExpression.find("id", id).singleResult();
return targetMatcher.match(expr);
}

Expand Down
63 changes: 32 additions & 31 deletions src/main/java/io/cryostat/graphql/ActiveRecordings.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import org.openjdk.jmc.common.unit.QuantityConversionException;

import io.cryostat.ConfigProperties;
import io.cryostat.core.templates.Template;
import io.cryostat.core.templates.TemplateType;
import io.cryostat.discovery.DiscoveryNode;
Expand All @@ -44,10 +45,10 @@
import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import io.smallrye.graphql.execution.ExecutionException;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jdk.jfr.RecordingState;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
import org.eclipse.microprofile.graphql.Mutation;
Expand All @@ -61,6 +62,9 @@ public class ActiveRecordings {
@Inject RecordingHelper recordingHelper;
@Inject Logger logger;

@ConfigProperty(name = ConfigProperties.CONNECTIONS_FAILED_TIMEOUT)
Duration timeout;

@Blocking
@Transactional
@Mutation
Expand Down Expand Up @@ -226,53 +230,55 @@ public List<ActiveRecording> createSnapshot(@NonNull DiscoveryNodeFilter nodes)
@Blocking
@Transactional
@Description("Start a new Flight Recording on the specified Target")
public Uni<ActiveRecording> doStartRecording(
public ActiveRecording doStartRecording(
@Source Target target, @NonNull RecordingSettings recording)
throws QuantityConversionException {
var fTarget = Target.<Target>findById(target.id);
var fTarget = Target.getTargetById(target.id);
Template template =
recordingHelper.getPreferredTemplate(
fTarget, recording.template, TemplateType.valueOf(recording.templateType));
return recordingHelper.startRecording(
fTarget,
Optional.ofNullable(recording.replace)
.map(RecordingReplace::valueOf)
.orElse(RecordingReplace.STOPPED),
template,
recording.asOptions(),
Optional.ofNullable(recording.metadata).map(s -> s.labels).orElse(Map.of()));
return recordingHelper
.startRecording(
fTarget,
Optional.ofNullable(recording.replace)
.map(RecordingReplace::valueOf)
.orElse(RecordingReplace.STOPPED),
template,
recording.asOptions(),
Optional.ofNullable(recording.metadata).map(s -> s.labels).orElse(Map.of()))
.await()
.atMost(timeout);
}

@Blocking
@Transactional
@Description("Create a new Flight Recorder Snapshot on the specified Target")
public Uni<ActiveRecording> doSnapshot(@Source Target target) {
var fTarget = Target.<Target>findById(target.id);
return recordingHelper.createSnapshot(fTarget);
public ActiveRecording doSnapshot(@Source Target target) {
var fTarget = Target.getTargetById(target.id);
return recordingHelper.createSnapshot(fTarget).await().atMost(timeout);
}

@Blocking
@Transactional
@Description("Stop the specified Flight Recording")
public Uni<ActiveRecording> doStop(@Source ActiveRecording recording) throws Exception {
var ar = ActiveRecording.<ActiveRecording>findById(recording.id);
return recordingHelper.stopRecording(ar);
public ActiveRecording doStop(@Source ActiveRecording recording) throws Exception {
var ar = ActiveRecording.<ActiveRecording>find("id", recording.id).singleResult();
return recordingHelper.stopRecording(ar).await().atMost(timeout);
}

@Blocking
@Transactional
@Description("Delete the specified Flight Recording")
public Uni<ActiveRecording> doDelete(@Source ActiveRecording recording) {
var ar = ActiveRecording.<ActiveRecording>findById(recording.id);
return recordingHelper.deleteRecording(ar);
public ActiveRecording doDelete(@Source ActiveRecording recording) {
var ar = ActiveRecording.<ActiveRecording>find("id", recording.id).singleResult();
return recordingHelper.deleteRecording(ar).await().atMost(timeout);
}

@Blocking
@Transactional
@Description("Archive the specified Flight Recording")
public Uni<ArchivedRecording> doArchive(@Source ActiveRecording recording) throws Exception {
var ar = ActiveRecording.<ActiveRecording>findById(recording.id);
return Uni.createFrom().item(recordingHelper.archiveRecording(ar, null, null));
public ArchivedRecording doArchive(@Source ActiveRecording recording) throws Exception {
var ar = ActiveRecording.<ActiveRecording>find("id", recording.id).singleResult();
return recordingHelper.archiveRecording(ar, null, null);
}

public TargetNodes.ActiveRecordings active(
Expand Down Expand Up @@ -319,14 +325,9 @@ public RecordingOptions asOptions() {
@Blocking
@Transactional
@Description("Updates the metadata labels for an existing Flight Recording.")
public Uni<ActiveRecording> doPutMetadata(
public ActiveRecording doPutMetadata(
@Source ActiveRecording recording, MetadataLabels metadataInput) {
return Uni.createFrom()
.item(
() -> {
return recordingHelper.updateRecordingMetadata(
recording.id, metadataInput.getLabels());
});
return recordingHelper.updateRecordingMetadata(recording.id, metadataInput.getLabels());
}

@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/cryostat/graphql/ArchivedRecordings.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public ArchivedRecording doDelete(@Source ArchivedRecording recording) {
return recording;
}

@Blocking
@NonNull
public ArchivedRecording doPutMetadata(
@Source ArchivedRecording recording, MetadataLabels metadataInput) {
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/io/cryostat/graphql/EnvironmentNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.cryostat.discovery.DiscoveryNode;
import io.cryostat.graphql.RootNode.DiscoveryNodeFilter;

import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
Expand All @@ -28,6 +29,7 @@
@GraphQLApi
public class EnvironmentNodes {

@Blocking
@Query("environmentNodes")
@Description("Get all environment nodes in the discovery tree with optional filtering")
public List<DiscoveryNode> environmentNodes(@Nullable DiscoveryNodeFilter filter) {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/io/cryostat/graphql/RootNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.cryostat.graphql.matchers.LabelSelectorMatcher;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Nullable;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
Expand All @@ -33,12 +34,14 @@
@GraphQLApi
public class RootNode {

@Blocking
@Query("rootNode")
@Description("Get the root target discovery node")
public DiscoveryNode getRootNode() {
return DiscoveryNode.getUniverse();
}

@Blocking
@Description(
"Get target nodes that are descendants of this node. That is, get the set of leaf nodes"
+ " from anywhere below this node's subtree.")
Expand Down
16 changes: 9 additions & 7 deletions src/main/java/io/cryostat/graphql/TargetNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import io.smallrye.common.annotation.Blocking;
import io.smallrye.graphql.api.Context;
import io.smallrye.graphql.api.Nullable;
import io.smallrye.mutiny.Uni;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.microprofile.graphql.Description;
import org.eclipse.microprofile.graphql.GraphQLApi;
Expand Down Expand Up @@ -75,9 +75,10 @@ public List<DiscoveryNode> getTargetNodes(DiscoveryNodeFilter filter) {
// }

@Blocking
@Transactional
public ActiveRecordings activeRecordings(
@Source Target target, @Nullable ActiveRecordingsFilter filter) {
var fTarget = Target.<Target>findById(target.id);
var fTarget = Target.getTargetById(target.id);
var recordings = new ActiveRecordings();
if (StringUtils.isNotBlank(fTarget.jvmId)) {
recordings.data =
Expand All @@ -92,7 +93,7 @@ public ActiveRecordings activeRecordings(
@Blocking
public ArchivedRecordings archivedRecordings(
@Source Target target, @Nullable ArchivedRecordingsFilter filter) {
var fTarget = Target.<Target>findById(target.id);
var fTarget = Target.getTargetById(target.id);
var recordings = new ArchivedRecordings();
if (StringUtils.isNotBlank(fTarget.jvmId)) {
recordings.data =
Expand All @@ -105,9 +106,10 @@ public ArchivedRecordings archivedRecordings(
}

@Blocking
@Transactional
@Description("Get the active and archived recordings belonging to this target")
public Recordings recordings(@Source Target target, Context context) {
var fTarget = Target.<Target>findById(target.id);
var fTarget = Target.getTargetById(target.id);
var recordings = new Recordings();
if (StringUtils.isBlank(fTarget.jvmId)) {
return recordings;
Expand All @@ -133,9 +135,9 @@ public Recordings recordings(@Source Target target, Context context) {

@Blocking
@Description("Get live MBean metrics snapshot from the specified Target")
public Uni<MBeanMetrics> mbeanMetrics(@Source Target target) {
var fTarget = Target.<Target>findById(target.id);
return connectionManager.executeConnectedTaskUni(fTarget, JFRConnection::getMBeanMetrics);
public MBeanMetrics mbeanMetrics(@Source Target target) {
var fTarget = Target.getTargetById(target.id);
return connectionManager.executeConnectedTask(fTarget, JFRConnection::getMBeanMetrics);
}

@SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
Expand Down
Loading

0 comments on commit aff1c63

Please sign in to comment.