春天似乎随机丢了一个豆子?

时间:2019-04-24 14:16:01

标签: java spring long-polling

我有一个奇怪的问题。

状态是EndpointStatus的类级别实例(构造函数中未提供工作)

private EndpointStatus status = new EndpointStatus(1L, EndpointStatus.Status.AVAILABLE);

....omitted....

@POST
@Path("/calculated")
public Response reCalculated(String req,
                         final @Context SecurityContext securityContext) {

   if ( status.isBusy() ) { return Response.ok( status.getCurrentJob() ).build(); }
        String uuid = UUID.randomUUID().toString();
        status.setStatus(EndpointStatus.Status.BUSY);

        CurrentJob job = new CurrentJob();
        job.setId(1L);
        job.setJobStatus("ACTIVE");
        job.setJobId(uuid);
        status.setCurrentJob(job);

        executorService.execute(() -> {
            try {
                thymeNewDateRange.getDataForDateRange(thymeDate, null, status);
                status.setCurrentJob(null);

            } catch (Exception e) {
                serverLogger.error(e);
            }
        });
        return Response.accepted(job).build();
}

所以我在这里收到POST

  1. 状态从可用->忙
  2. 更改
  3. 使用生成的UUID创建作业obj。
  4. 然后将作业对象设置为状态obj。
  5. 使用UUID(长期运行的作业)立即返回202

从初始职位返回:(职位类别)

{
"id" : 1,
"jobId" : "5d974c2d-e01a-4842-ad5f-1ef7d78901c0",
"jobStatus" : "ACTIVE",
}

这里的一切都很好。客户端已经开始查询5d974c2d-e01a-4842-ad5f-1ef7d78901c0作为url,只要结果还没有准备好,它就会返回相同的JSON。

但是但是

在前几次查询后不久(在此SO帖子之前,客户端运行了3个查询,在此之前是5个,所以是随机的)

status.setCurrentJob(null);

似乎会被调用(在POST方法中长时间运行的工作之下) 即使作业刚刚开始,这也将使端点从繁忙返回到可用状态。

设置为空后,作业端点将响应:(由于currentJob设置为null,所以返回了状态类)

{
"id" : 1,
"status" : "AVAILABLE",
"currentJob" : null,
"busy" : false
 }

这又将停止从客户端查询,因此客户端将丢失所有数据。

不应该

 status.setCurrentJob(null);

之后被调用
thymeNewDateRange.getDataForDateRange(thymeDate, null, status);

完成了吗?在整个应用程序中,这是将job设置为null的唯一实例,因此应该从此处传播?

用于查询工作的端点

@GET
@Path("/job")
public Response queryJob(@Context SecurityContext securityContext,
                          @QueryParam("pid") String pid) {

    if( status.getCurrentJob() != null ) {
        return Response.ok(status.getCurrentJob()).build();

    }
    if( status.getStatus() == EndpointStatus.Status.AVAILABLE ) {
        //JOB HAS ENDED - but this will still trigger too early
        return Response.ok(status).build();
    }else {
        return Response.ok("ERROR STATE").build();
    }


}

请随时问我忘记提及的任何问题。.这是一篇冗长而复杂的帖子。

干杯;)

编辑,我需要帮助或驱魔人...

尝试使用volatile(谢谢@paulturnip),但没有帮助

此外,该问题似乎仅在“真实”测试服务器上仍然存在。 当使用localhost:8080在本地运行时,此问题永远不会出现...

但是在服务器上运行时,这种情况一直在发生。

我将logger作为@Path(“ / job”)的第一行添加到日志:

serverLogger.info("STATUS: " + status.getStatus().toString() + " JOB STATUS: " + status.getCurrentJob().getJobStatus() );

在本地,再次没有nullPointer。但是只要在适当的服务器环境上运行,status.getCurrentJob().getJobStatus()就会以某种方式抛出NullPointerException,甚至是

CurrentJob job = new CurrentJob();
        job.setId(1L);
        job.setJobStatus("ACTIVE");
        job.setJobId(uuid);

        status.setCurrentJob(job);

已设置,字面上是(/ calculated)之前的一个呼叫

EDIT2:

CurrentJob bean:

@Entity
public class CurrentJob {

@Id
private Long id;
private volatile String jobId;
private volatile String jobStatus;

.... basic getter&setter&constructor ....

我正在使用休眠模式,所以使用@Entity和@Id,但是由于我不打算保存该实例,我想知道它们是否可能会干扰状态?

0 个答案:

没有答案