0

"Couldn't store job: Unable to store Job: 'QbBackupGroup.QbBackup', because one already exists with this identification."

I'm getting this anytime after the first run on a clean database (SQLCE). I've searched and found a few suggestions (i.e. here and here), but they pertain to running Quartz.NET without TopShelf.

The suggested code is based on standard Quartz.NET architecture (e.g. variables and values), but the Quartz.NET code for TopShelf is all delegates. Nothing seems to directly translate.

My code is below.

However... all that said... it may not matter, as my eventual goal is to be able to add/remove jobs/triggers at runtime without restarting the service. This hard-coded design may not even apply, but I haven't figured out how to do the runtime bit yet.

If I can get past this, the runtime bit is next. Unless the runtime bit negates the need for this. Catch-21.

Please advise.

Service:

Sub Main()
    Dim oSchedule As Action(Of SimpleScheduleBuilder)
    Dim oTrigger As Func(Of ITrigger)
    Dim oDetail As Func(Of IJobDetail)
    Dim oJob As Action(Of QuartzConfigurator)

    oSchedule = Function(ScheduleBuilder) As SimpleScheduleBuilder
                  Return ScheduleBuilder.WithIntervalInSeconds(5).RepeatForever
                End Function

    oTrigger = Function() As ITrigger
                 Return TriggerBuilder.Create.WithIdentity(QbBackup.Job.Trigger, QbBackup.Job.Group).WithSimpleSchedule(oSchedule).Build
               End Function

    oDetail = Function()
                Return JobBuilder.Create(Of QbBackup.Job).WithIdentity(QbBackup.Job.Name, QbBackup.Job.Group).Build
              End Function

    oJob = Function(Configurator As QuartzConfigurator)
             Return Configurator.WithJob(oDetail).AddTrigger(oTrigger)
           End Function

    HostFactory.Run(Sub(Configurator)
                      Configurator.Service(Of Manager)(Sub(Service)
                                                         Service.ConstructUsing(Function(Factory) As ServiceControl
                                                                                  Return New Manager
                                                                                End Function)

                                                         Service.WhenStarted(Function(Notifier, HostControl) As Boolean
                                                                               Return Notifier.StartService(HostControl)
                                                                             End Function)

                                                         Service.WhenStopped(Function(Notifier, HostControl) As Boolean
                                                                               Return Notifier.StopService(HostControl)
                                                                             End Function)

                                                         Service.ScheduleQuartzJob(oJob)
                                                       End Sub)

                      Configurator.SetDescription(SchedulerInfo.Description)
                      Configurator.SetServiceName(SchedulerInfo.Product)
                      Configurator.SetDisplayName(SchedulerInfo.Title)
                      Configurator.StartAutomatically()
                      Configurator.RunAsLocalSystem()
                    End Sub)
End Sub

Job:

Imports Common.Logging

Public Class Job
  Implements IJob

  Private Shared Logger As ILog = LogManager.GetLogger(GetType(Job))

  Public Sub Execute(Context As IJobExecutionContext) Implements IJob.Execute
    Try
      Job.Logger.Info(Now.ToString)

    Catch ex As Exception
      Throw New JobExecutionException(ex.Message, ex)

    End Try
  End Sub



  Public Shared ReadOnly Property Name As String
    Get
      Return QbBackupInfo.Product
    End Get
  End Property



  Public Shared ReadOnly Property Trigger As String
    Get
      Return "{0}Trigger".ToFormat(Job.Name)
    End Get
  End Property



  Public Shared ReadOnly Property Group As String
    Get
      Return "{0}Group".ToFormat(Job.Name)
    End Get
  End Property
End Class

App.config:

<quartz>
  <!-- Configure Scheduler -->
  <add key="quartz.scheduler.instanceName" value="Scheduler" />
  <add key="quartz.scheduler.instanceId" value="Scheduler" />
  <!-- Configure Thread Pool -->
  <add key="quartz.threadPool.type" value="Quartz.Simpl.SimpleThreadPool, Quartz" />
  <add key="quartz.threadPool.threadCount" value="10" />
  <add key="quartz.threadPool.threadPriority" value="Normal" />
  <!-- Configure Job Store -->
  <add key="quartz.jobStore.misfireThreshold" value="60000" />
  <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
  <add key="quartz.jobStore.useProperties" value="true" />
  <add key="quartz.jobStore.dataSource" value="default" />
  <add key="quartz.jobStore.tablePrefix" value="QRTZ_" />
  <add key="quartz.jobStore.lockHandler.type" value="Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz" />
  <!-- Configure Data Source -->
  <add key="quartz.dataSource.default.connectionString" value="Data Source=C:\ProgramData\Scheduler\Scheduler.sdf;Max Database Size=4091;Persist Security Info=False;" />
  <add key="quartz.dataSource.default.provider" value="SqlServerCe-400" />
</quartz>
Community
  • 1
  • 1
InteXX
  • 6,135
  • 6
  • 43
  • 80

1 Answers1

1

The combination of a job's group and its name are the job's unique key in Quartz.Net. They should be unique across all jobs. The same happens for triggers. The fix is to change the job's name for each job if you really need to have multiple jobs of the same type running. You can also just have one job with multiple triggers instead. Each trigger has its own data map so you could add custom information there. One way to get around this is to append a timestamp the job's name so that they are all uniquely named.

jvilalta
  • 6,679
  • 1
  • 28
  • 36
  • Hi Jay, thanks for your reply. FYI that was me on the [Google Groups question](https://groups.google.com/forum/#!topic/quartznet/hFvUtxiPURA) as well. Actually, I don't need to have multiple same-typed jobs running--I'm just trying to get an AdoJobStore-backed job/schedule to run a second time. This is a companion problem to the 'Runtime Scheduling' problem -- I believe that the answer to one is going to be the answer to the other. – InteXX Oct 14 '14 at 21:22