├── .gitignore
├── .semver
├── Gemfile
├── MassTransit.snk
├── README.md
├── build_support
├── BuildUtils.rb
├── util.rb
└── versioning.rb
├── rakefile.rb
├── setup_sql_server.sql
└── src
├── .nuget
├── NuGet.Config
├── NuGet.targets
└── packages.config
├── MassTransit.Quartz.sln
├── MassTransit.Quartz.sln.DotSettings
├── MassTransit.QuartzIntegration.Tests
├── App.config
├── ContextSetup.cs
├── JobDetail_Specs.cs
├── MassTransit.QuartzIntegration.Tests.csproj
├── PastEvent_Specs.cs
├── Service_Specs.cs
├── Syntax_Specs.cs
├── Utils.cs
├── job_scheduling_data_2_0.xsd
├── log4net.config
└── packages.config
├── MassTransit.QuartzIntegration
├── CancelScheduledMessageConsumer.cs
├── CancelScheduledTimeoutConsumer.cs
├── MassTransit.QuartzIntegration.csproj
├── MassTransitJobFactory.cs
├── ScheduleMessageConsumer.cs
├── ScheduleMessageJobBuilder.cs
├── ScheduleMessageJobBuilderImpl.cs
├── ScheduleTimeoutConsumer.cs
├── ScheduledMessageContext.cs
├── ScheduledMessageJob.cs
├── ScheduledTimeoutJob.cs
├── job_scheduling_data_2_0.xsd
└── packages.config
├── MassTransit.QuartzService
├── Configuration
│ ├── ConfigurationProviderExtensions.cs
│ ├── ConnectionStringProvider.cs
│ ├── FileConfigurationProvider.cs
│ ├── IConfigurationProvider.cs
│ ├── IConnectionProvider.cs
│ ├── IConnectionStringProvider.cs
│ └── SqlConnectionProvider.cs
├── MassTransit.QuartzService.csproj
├── Program.cs
├── ScheduleMessageService.cs
├── app.config
├── job_scheduling_data_2_0.xsd
├── log4net.config
└── packages.config
├── MassTransit.Scheduling
├── CancelScheduledMessage.cs
├── MassTransit.Scheduling.csproj
├── ScheduleMessage.cs
├── ScheduleMessageExtensions.cs
├── ScheduledMessage.cs
└── packages.config
└── packages
└── repositories.config
/.gitignore:
--------------------------------------------------------------------------------
1 | build_artifacts/*
2 | build_output/*
3 |
4 | **/*.suo
5 | **/**/*.suo
6 | **/*.user
7 | **/**/*.user
8 |
9 | bin
10 | obj
11 | _ReSharper*
12 | *.dotCover
13 |
14 | *.csproj.user
15 | *.resharper.user
16 | *.ReSharper.user
17 | *.cache
18 | *~
19 | *.swp
20 | *.bak
21 | *.orig
22 | *.user
23 |
24 | NuGet.exe
25 | src/packages/**/*
26 | docs/build/**/*
27 |
28 | .DS_Store
29 |
30 | TestResult.xml
31 | submit.xml
32 | src/tests/*
33 | tests/*
34 | SolutionVersion.cs
35 |
--------------------------------------------------------------------------------
/.semver:
--------------------------------------------------------------------------------
1 | ---
2 | :major: 1
3 | :minor: 2
4 | :patch: 12
5 | :special: ''
6 | :metadata: ''
7 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'albacore', '~> 0.3.6'
4 | gem 'rake'
5 | gem 'semver2'
--------------------------------------------------------------------------------
/MassTransit.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MassTransit/MassTransit-Quartz/49807746daa64b7573b0a1346f81f2f84e557918/MassTransit.snk
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | MassTransit-Quartz
2 | ==================
3 |
4 | Quartz support for MassTransit
5 |
6 | Possible API
7 | ==============
8 |
9 | Create a service that will allow messages to be scheduled.
10 |
11 | For example,
12 |
13 | var handle = bus.SchedulePublish(30.Seconds().FromNow, new MyMessage(someId, someValue));
14 |
15 | The default implementation can be in memory, but we can also serialize the message to Json and store it for later resubmission via the bus.
16 |
17 | Should probably have a SchedulePublish() and a ScheduleSend(endpoint, ...) so that direct sends as well as publishes can be supported, including forging the sender address to be that of the original requestor (instead of the scheduled message service).
18 |
19 | Guid tokenId = handle.TokenId;
20 |
21 | bus.CancelScheduledMessage(tokenId);
22 | or handle.Cancel(); if the handle is still around (just a closure around the bus and method).
--------------------------------------------------------------------------------
/build_support/BuildUtils.rb:
--------------------------------------------------------------------------------
1 | require 'erb'
2 |
3 | class NUnitRunner
4 | include FileTest
5 |
6 | def initialize(command, working_directory, framework, flags)
7 | @command = command
8 | @working_directory = working_directory
9 | @framework = framework || 'v4.0'
10 | @flags = flags
11 |
12 | # prepare the command
13 | @cmd = "#{command} /framework=#{@framework}"
14 | @cmd += ' ' + @flags.join(' ') unless @flags.nil?
15 | end
16 |
17 | def run(assemblies)
18 | assemblies.each do |assem|
19 | file = File.expand_path("#{@working_directory}/#{assem}")
20 | Kernel::system("#{@cmd} \"#{file}\"")
21 | end
22 | end
23 | end
24 |
25 | class MSBuildRunner
26 | def self.compile(attributes)
27 | build_config = attributes.fetch(:build_config)
28 | solutionFile = attributes[:solutionfile]
29 |
30 | attributes[:projFile] = solutionFile
31 | attributes[:properties] ||= []
32 | attributes[:properties] << "Configuration=#{build_config}"
33 | attributes[:extraSwitches] = ["maxcpucount:2", "v:m", "t:rebuild"]
34 |
35 | self.runProjFile(attributes);
36 | end
37 |
38 | def self.runProjFile(attributes)
39 | version = attributes.fetch(:clrversion, 'v4.0.30319')
40 | build_config = attributes.fetch(:build_config, 'debug')
41 | projFile = attributes[:projFile]
42 |
43 | frameworkDir = File.join(ENV['windir'].dup, 'Microsoft.NET', 'Framework', version)
44 | msbuildFile = File.join(frameworkDir, 'msbuild.exe')
45 |
46 | properties = attributes.fetch(:properties, [])
47 |
48 | switchesValue = ""
49 |
50 | properties.each do |prop|
51 | switchesValue += " /property:#{prop}"
52 | end
53 |
54 | extraSwitches = attributes.fetch(:extraSwitches, [])
55 |
56 | extraSwitches.each do |switch|
57 | switchesValue += " /#{switch}"
58 | end
59 |
60 | targets = attributes.fetch(:targets, [])
61 | targetsValue = ""
62 | targets.each do |target|
63 | targetsValue += " /t:#{target}"
64 | end
65 |
66 | Kernel::system("#{msbuildFile} #{projFile} #{targetsValue} #{switchesValue}")
67 | end
68 | end
69 |
70 | class AspNetCompilerRunner
71 | def self.compile(attributes)
72 |
73 | webPhysDir = attributes.fetch(:webPhysDir, '')
74 | webVirDir = attributes.fetch(:webVirDir, 'This_Value_Is_Not_Used')
75 |
76 | frameworkDir = File.join(ENV['windir'].dup, 'Microsoft.NET', 'Framework', 'v4.0.30319')
77 | aspNetCompiler = File.join(frameworkDir, 'aspnet_compiler.exe')
78 |
79 | Kernel::system("#{aspNetCompiler} -nologo -errorstack -c -p #{webPhysDir} -v #{webVirDir}")
80 | end
81 | end
82 |
83 | class AsmInfoBuilder
84 | attr_reader :buildnumber
85 |
86 | def initialize(baseVersion, properties)
87 | @properties = properties;
88 |
89 | @buildnumber = baseVersion + (ENV["CCNetLabel"].nil? ? '0' : ENV["CCNetLabel"].to_s)
90 | @properties['Version'] = @properties['InformationalVersion'] = buildnumber;
91 | end
92 |
93 |
94 |
95 | def write(file)
96 | template = %q{
97 | using System;
98 | using System.Reflection;
99 | using System.Runtime.InteropServices;
100 |
101 | <% @properties.each {|k, v| %>
102 | [assembly: Assembly<%=k%>Attribute("<%=v%>")]
103 | <% } %>
104 | }.gsub(/^ /, '')
105 |
106 | erb = ERB.new(template, 0, "%<>")
107 |
108 | File.open(file, 'w') do |file|
109 | file.puts erb.result(binding)
110 | end
111 | end
112 | end
113 |
--------------------------------------------------------------------------------
/build_support/util.rb:
--------------------------------------------------------------------------------
1 | def waitfor(&block)
2 | checks = 0
3 |
4 | until block.call || checks >10
5 | sleep 0.5
6 | checks += 1
7 | end
8 |
9 | raise 'Waitfor timeout expired. Make sure that you aren\'t running something from the build output folders, or that you have browsed to it through Explorer.' if checks > 10
10 | end
11 |
12 | def get_commit_hash_and_date
13 | begin
14 | commit = `git log -1 --pretty=format:%H`
15 | git_date = `git log -1 --date=iso --pretty=format:%ad`
16 | commit_date = DateTime.parse( git_date ).strftime("%Y-%m-%d %H%M%S")
17 | rescue
18 | commit = "git unavailable"
19 | end
20 |
21 | [commit, commit_date]
22 | end
--------------------------------------------------------------------------------
/build_support/versioning.rb:
--------------------------------------------------------------------------------
1 | require 'semver'
2 |
3 | def commit_data
4 | begin
5 | commit = `git rev-parse --short HEAD`.chomp()[0,6]
6 | git_date = `git log -1 --date=iso --pretty=format:%ad`
7 | commit_date = DateTime.parse( git_date ).strftime("%Y-%m-%d %H%M%S")
8 | rescue Exception => e
9 | puts e.inspect
10 | commit = (ENV['BUILD_VCS_NUMBER'] || "000000")[0,6]
11 | commit_date = Time.new.strftime("%Y-%m-%d %H%M%S")
12 | end
13 | [commit, commit_date]
14 | end
15 |
16 | task :versioning do
17 | ver = SemVer.find
18 | revision = (ENV['BUILD_NUMBER'] || ver.patch).to_i
19 | var = SemVer.new(ver.major, ver.minor, revision, ver.special)
20 |
21 | # extensible number w/ git hash
22 | ENV['BUILD_VERSION'] = BUILD_VERSION = ver.format("%M.%m.%p%s") + ".#{commit_data()[0]}"
23 |
24 | # nuget (not full semver 2.0.0-rc.1 support) see http://nuget.codeplex.com/workitem/1796
25 | ENV['NUGET_VERSION'] = NUGET_VERSION = ver.format("%M.%m.%p%s")
26 |
27 | # purely M.m.p format
28 | ENV['FORMAL_VERSION'] = FORMAL_VERSION = "#{ SemVer.new(ver.major, ver.minor, revision).format "%M.%m.%p"}"
29 | puts "##teamcity[buildNumber '#{BUILD_VERSION}']" # tell teamcity our decision
30 | end
--------------------------------------------------------------------------------
/rakefile.rb:
--------------------------------------------------------------------------------
1 | COPYRIGHT = "Copyright 2012-2013 Chris Patterson, Albert Hives."
2 |
3 | require File.dirname(__FILE__) + "/build_support/BuildUtils.rb"
4 | require File.dirname(__FILE__) + "/build_support/util.rb"
5 | include FileTest
6 | require 'albacore'
7 | require File.dirname(__FILE__) + "/build_support/versioning.rb"
8 |
9 | PRODUCT = 'MassTransit-Quartz'
10 | CLR_TOOLS_VERSION = 'v4.0.30319'
11 | OUTPUT_PATH = 'bin/Release'
12 |
13 | props = {
14 | :src => File.expand_path("src"),
15 | :nuget => File.join(File.expand_path("src"), ".nuget", "nuget.exe"),
16 | :output => File.expand_path("build_output"),
17 | :artifacts => File.expand_path("build_artifacts"),
18 | :lib => File.expand_path("lib"),
19 | :projects => ["MassTransit-Quartz"],
20 | :keyfile => File.expand_path("MassTransit.snk")
21 | }
22 |
23 | desc "Cleans, compiles, il-merges, unit tests, prepares examples, packages zip"
24 | task :all => [:default, :package]
25 |
26 | desc "**Default**, compiles and runs tests"
27 | task :default => [:clean, :nuget_restore, :compile, :package]
28 |
29 | desc "Update the common version information for the build. You can call this task without building."
30 | assemblyinfo :global_version => [:versioning] do |asm|
31 | # Assembly file config
32 | asm.product_name = PRODUCT
33 | asm.description = "MassTransit-Quartz provides message scheduling for MassTransit services."
34 | asm.version = FORMAL_VERSION
35 | asm.file_version = FORMAL_VERSION
36 | asm.custom_attributes :AssemblyInformationalVersion => "#{BUILD_VERSION}",
37 | :ComVisibleAttribute => false,
38 | :CLSCompliantAttribute => true
39 | asm.copyright = COPYRIGHT
40 | asm.output_file = 'src/SolutionVersion.cs'
41 | asm.namespaces "System", "System.Reflection", "System.Runtime.InteropServices"
42 | end
43 |
44 | desc "Prepares the working directory for a new build"
45 | task :clean do
46 | FileUtils.rm_rf props[:output]
47 | waitfor { !exists?(props[:output]) }
48 |
49 | FileUtils.rm_rf props[:artifacts]
50 | waitfor { !exists?(props[:artifacts]) }
51 |
52 | Dir.mkdir props[:output]
53 | Dir.mkdir props[:artifacts]
54 | end
55 |
56 | desc "Cleans, versions, compiles the application and generates build_output/."
57 | task :compile => [:versioning, :global_version, :build4, :tests4, :copy4]
58 |
59 | task :copy35 => [:build35] do
60 | copyOutputFiles File.join(props[:src], "MassTransit.Scheduling/bin/Release/v3.5"), "MassTransit.Scheduling.{dll,pdb,xml}", File.join(props[:output], 'Scheduling', 'net-3.5')
61 | end
62 |
63 | task :copy4 => [:build4] do
64 | copyOutputFiles File.join(props[:src], "MassTransit.Scheduling/bin/Release"), "MassTransit.Scheduling.{dll,pdb,xml}", File.join(props[:output], 'Scheduling', 'net-4.0-full')
65 | copyOutputFiles File.join(props[:src], "MassTransit.QuartzIntegration/bin/Release"), "MassTransit.QuartzIntegration.{dll,pdb,xml}", File.join(props[:output], 'Integration', 'net-4.0-full')
66 |
67 | copyOutputFiles File.join(props[:src], "MassTransit.QuartzService/bin/Release"), "MassTransit.QuartzService.exe", File.join(props[:output], 'Service')
68 | copyOutputFiles File.join(props[:src], "MassTransit.QuartzService/bin/Release"), "*.dll", File.join(props[:output], 'Service')
69 | copyOutputFiles File.join(props[:src], "MassTransit.QuartzService/bin/Release"), "*.config", File.join(props[:output], 'Service')
70 | end
71 |
72 | desc "Only compiles the application."
73 | msbuild :build4 do |msb|
74 | msb.properties :Configuration => "Release",
75 | :Platform => 'Any CPU'
76 | msb.use :net4
77 | msb.targets :Rebuild
78 | msb.properties[:SignAssembly] = 'true'
79 | msb.properties[:AssemblyOriginatorKeyFile] = props[:keyfile]
80 | msb.solution = 'src/MassTransit.Quartz.sln'
81 | end
82 |
83 | def copyOutputFiles(fromDir, filePattern, outDir)
84 | FileUtils.mkdir_p outDir unless exists?(outDir)
85 | Dir.glob(File.join(fromDir, filePattern)){|file|
86 | copy(file, outDir) if File.file?(file)
87 | }
88 | end
89 |
90 | desc "Runs unit tests"
91 | nunit :tests4 => [:build4] do |nunit|
92 | nunit.command = File.join('src', 'packages','NUnit.Runners.2.6.3', 'tools', 'nunit-console.exe')
93 | nunit.parameters = "/framework=#{CLR_TOOLS_VERSION}", '/nothread', '/nologo', '/labels', "\"/xml=#{File.join(props[:artifacts], 'nunit-test-results-net-4.0.xml')}\""
94 | nunit.assemblies = FileList[File.join(props[:src], "MassTransit.QuartzIntegration.Tests/bin/Release", "MassTransit.QuartzIntegration.Tests.dll")]
95 | end
96 |
97 | task :package => [:nuget, :zip_output]
98 |
99 | desc "ZIPs up the build results."
100 | zip :zip_output => [:versioning] do |zip|
101 | zip.directories_to_zip = [props[:output]]
102 | zip.output_file = "MassTransit-Quartz-#{NUGET_VERSION}.zip"
103 | zip.output_path = props[:artifacts]
104 | end
105 |
106 | desc "restores missing packages"
107 | msbuild :nuget_restore do |msb|
108 | msb.properties :SolutionDir => "../"
109 | msb.use :net4
110 | msb.targets :RestorePackages
111 | msb.solution = File.join(props[:src], "MassTransit.Scheduling", "MassTransit.Scheduling.csproj")
112 | end
113 |
114 | desc "Builds the nuget package"
115 | task :nuget => [:versioning, :create_nuspec] do
116 | sh "#{props[:nuget]} pack #{props[:artifacts]}/MassTransit.Scheduling.nuspec /Symbols /OutputDirectory #{props[:artifacts]}"
117 | sh "#{props[:nuget]} pack #{props[:artifacts]}/MassTransit.QuartzIntegration.nuspec /Symbols /OutputDirectory #{props[:artifacts]}"
118 | end
119 |
120 | nuspec :create_nuspec do |nuspec|
121 | nuspec.id = 'MassTransit.Scheduling'
122 | nuspec.version = NUGET_VERSION
123 | nuspec.authors = 'Chris Patterson, Albert Hives'
124 | nuspec.summary = 'Scheduled messaging for MassTransit'
125 | nuspec.description = 'MassTransit Scheduling is used to schedule future message delivery'
126 | nuspec.title = 'MassTransit.Scheduling'
127 | nuspec.projectUrl = 'http://github.com/MassTransit/MassTransit-Quartz'
128 | nuspec.iconUrl = 'http://MassTransit-project.com/wp-content/themes/pandora/slide.1.png'
129 | nuspec.language = "en-US"
130 | nuspec.licenseUrl = "http://www.apache.org/licenses/LICENSE-2.0"
131 | nuspec.requireLicenseAcceptance = "false"
132 | nuspec.dependency "Magnum", "2.1.3"
133 | nuspec.dependency "MassTransit", "2.10.2"
134 | nuspec.output_file = File.join(props[:artifacts], 'MassTransit.Scheduling.nuspec')
135 | add_files File.join(props[:output], 'Scheduling'), 'MassTransit.Scheduling.{dll,pdb,xml}', nuspec
136 | nuspec.file(File.join(props[:src], "MassTransit.Scheduling\\**\\*.cs").gsub("/","\\"), "src")
137 | end
138 |
139 | nuspec :create_nuspec do |nuspec|
140 | nuspec.id = 'MassTransit.QuartzIntegration'
141 | nuspec.version = NUGET_VERSION
142 | nuspec.authors = 'Chris Patterson, Albert Hives'
143 | nuspec.summary = 'Quartz integration for MassTransit'
144 | nuspec.description = 'Adds support for Quartz as a message scheduler to MassTransit (used by the MassTransit.QuartzService project)'
145 | nuspec.title = 'MassTransit.QuartzIntegration'
146 | nuspec.projectUrl = 'http://github.com/MassTransit/MassTransit-Quartz'
147 | nuspec.iconUrl = 'http://MassTransit-project.com/wp-content/themes/pandora/slide.1.png'
148 | nuspec.language = "en-US"
149 | nuspec.licenseUrl = "http://www.apache.org/licenses/LICENSE-2.0"
150 | nuspec.requireLicenseAcceptance = "false"
151 | nuspec.dependency "Magnum", "2.1.3"
152 | nuspec.dependency "MassTransit", "2.10.2"
153 | nuspec.dependency "MassTransit.Scheduling", NUGET_VERSION
154 | nuspec.dependency "Common.Logging", "3.0.0"
155 | nuspec.dependency "Newtonsoft.Json", "6.0.6"
156 | nuspec.dependency "Quartz", "2.3.2"
157 | nuspec.output_file = File.join(props[:artifacts], 'MassTransit.QuartzIntegration.nuspec')
158 | add_files File.join(props[:output], 'Integration'), 'MassTransit.QuartzIntegration.{dll,pdb,xml}', nuspec
159 | nuspec.file(File.join(props[:src], "MassTransit.QuartzIntegration\\**\\*.cs").gsub("/","\\"), "src")
160 | end
161 |
162 | def project_outputs(props)
163 | props[:projects].map{ |p| "src/#{p}/bin/#{BUILD_CONFIG}/#{p}.dll" }.
164 | concat( props[:projects].map{ |p| "src/#{p}/bin/#{BUILD_CONFIG}/#{p}.exe" } ).
165 | find_all{ |path| exists?(path) }
166 | end
167 |
168 | def get_commit_hash_and_date
169 | begin
170 | commit = `git log -1 --pretty=format:%H`
171 | git_date = `git log -1 --date=iso --pretty=format:%ad`
172 | commit_date = DateTime.parse( git_date ).strftime("%Y-%m-%d %H%M%S")
173 | rescue
174 | commit = "git unavailable"
175 | end
176 |
177 | [commit, commit_date]
178 | end
179 |
180 | def add_files stage, what_dlls, nuspec
181 | [['net35', 'net-3.5'], ['net40', 'net-4.0'], ['net40-full', 'net-4.0-full']].each{|fw|
182 | takeFrom = File.join(stage, fw[1], what_dlls)
183 | Dir.glob(takeFrom).each do |f|
184 | nuspec.file(f.gsub("/", "\\"), "lib\\#{fw[0]}")
185 | end
186 | }
187 | end
188 |
189 | def waitfor(&block)
190 | checks = 0
191 |
192 | until block.call || checks >10
193 | sleep 0.5
194 | checks += 1
195 | end
196 |
197 | raise 'Waitfor timeout expired. Make sure that you aren\'t running something from the build output folders, or that you have browsed to it through Explorer.' if checks > 10
198 | end
199 |
--------------------------------------------------------------------------------
/setup_sql_server.sql:
--------------------------------------------------------------------------------
1 | --# thanks to George Papastamatopoulos for submitting this ... and Marko Lahma for
2 | --# updating it.
3 |
4 | USE [quartz]
5 | GO
6 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
7 | ALTER TABLE [dbo].[QRTZ_TRIGGERS] DROP CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS
8 | GO
9 |
10 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
11 | ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] DROP CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS
12 | GO
13 |
14 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
15 | ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS
16 | GO
17 |
18 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISFOREIGNKEY') = 1)
19 | ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] DROP CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS
20 | GO
21 |
22 | IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]'))
23 | ALTER TABLE [dbo].[QRTZ_JOB_LISTENERS] DROP CONSTRAINT [FK_QRTZ_JOB_LISTENERS_QRTZ_JOB_DETAILS]
24 |
25 | IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[dbo].[FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]') AND parent_object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]'))
26 | ALTER TABLE [dbo].[QRTZ_TRIGGER_LISTENERS] DROP CONSTRAINT [FK_QRTZ_TRIGGER_LISTENERS_QRTZ_TRIGGERS]
27 |
28 |
29 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CALENDARS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
30 | DROP TABLE [dbo].[QRTZ_CALENDARS]
31 | GO
32 |
33 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_CRON_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
34 | DROP TABLE [dbo].[QRTZ_CRON_TRIGGERS]
35 | GO
36 |
37 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_BLOB_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
38 | DROP TABLE [dbo].[QRTZ_BLOB_TRIGGERS]
39 | GO
40 |
41 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_FIRED_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
42 | DROP TABLE [dbo].[QRTZ_FIRED_TRIGGERS]
43 | GO
44 |
45 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_PAUSED_TRIGGER_GRPS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
46 | DROP TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS]
47 | GO
48 |
49 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_JOB_LISTENERS]') AND type in (N'U'))
50 | DROP TABLE [dbo].[QRTZ_JOB_LISTENERS]
51 |
52 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SCHEDULER_STATE]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
53 | DROP TABLE [dbo].[QRTZ_SCHEDULER_STATE]
54 | GO
55 |
56 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_LOCKS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
57 | DROP TABLE [dbo].[QRTZ_LOCKS]
58 | GO
59 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGER_LISTENERS]') AND type in (N'U'))
60 | DROP TABLE [dbo].[QRTZ_TRIGGER_LISTENERS]
61 |
62 |
63 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_JOB_DETAILS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
64 | DROP TABLE [dbo].[QRTZ_JOB_DETAILS]
65 | GO
66 |
67 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPLE_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
68 | DROP TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS]
69 | GO
70 |
71 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_SIMPROP_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
72 | DROP TABLE [dbo].QRTZ_SIMPROP_TRIGGERS
73 | GO
74 |
75 | IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[QRTZ_TRIGGERS]') AND OBJECTPROPERTY(id, N'ISUSERTABLE') = 1)
76 | DROP TABLE [dbo].[QRTZ_TRIGGERS]
77 | GO
78 |
79 | CREATE TABLE [dbo].[QRTZ_CALENDARS] (
80 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
81 | [CALENDAR_NAME] [NVARCHAR] (200) NOT NULL ,
82 | [CALENDAR] [IMAGE] NOT NULL
83 | ) ON [PRIMARY]
84 | GO
85 |
86 | CREATE TABLE [dbo].[QRTZ_CRON_TRIGGERS] (
87 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
88 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
89 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
90 | [CRON_EXPRESSION] [NVARCHAR] (120) NOT NULL ,
91 | [TIME_ZONE_ID] [NVARCHAR] (80)
92 | ) ON [PRIMARY]
93 | GO
94 |
95 | CREATE TABLE [dbo].[QRTZ_FIRED_TRIGGERS] (
96 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
97 | [ENTRY_ID] [NVARCHAR] (95) NOT NULL ,
98 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
99 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
100 | [INSTANCE_NAME] [NVARCHAR] (200) NOT NULL ,
101 | [FIRED_TIME] [BIGINT] NOT NULL ,
102 | [PRIORITY] [INTEGER] NOT NULL ,
103 | [STATE] [NVARCHAR] (16) NOT NULL,
104 | [JOB_NAME] [NVARCHAR] (150) NULL ,
105 | [JOB_GROUP] [NVARCHAR] (150) NULL ,
106 | [IS_NONCONCURRENT] BIT NULL ,
107 | [REQUESTS_RECOVERY] BIT NULL
108 | ) ON [PRIMARY]
109 | GO
110 |
111 | CREATE TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] (
112 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
113 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL
114 | ) ON [PRIMARY]
115 | GO
116 |
117 | CREATE TABLE [dbo].[QRTZ_SCHEDULER_STATE] (
118 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
119 | [INSTANCE_NAME] [NVARCHAR] (200) NOT NULL ,
120 | [LAST_CHECKIN_TIME] [BIGINT] NOT NULL ,
121 | [CHECKIN_INTERVAL] [BIGINT] NOT NULL
122 | ) ON [PRIMARY]
123 | GO
124 |
125 | CREATE TABLE [dbo].[QRTZ_LOCKS] (
126 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
127 | [LOCK_NAME] [NVARCHAR] (40) NOT NULL
128 | ) ON [PRIMARY]
129 | GO
130 |
131 | CREATE TABLE [dbo].[QRTZ_JOB_DETAILS] (
132 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
133 | [JOB_NAME] [NVARCHAR] (150) NOT NULL ,
134 | [JOB_GROUP] [NVARCHAR] (150) NOT NULL ,
135 | [DESCRIPTION] [NVARCHAR] (250) NULL ,
136 | [JOB_CLASS_NAME] [NVARCHAR] (250) NOT NULL ,
137 | [IS_DURABLE] BIT NOT NULL ,
138 | [IS_NONCONCURRENT] BIT NOT NULL ,
139 | [IS_UPDATE_DATA] BIT NOT NULL ,
140 | [REQUESTS_RECOVERY] BIT NOT NULL ,
141 | [JOB_DATA] [IMAGE] NULL
142 | ) ON [PRIMARY]
143 | GO
144 |
145 | CREATE TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] (
146 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
147 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
148 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
149 | [REPEAT_COUNT] [INTEGER] NOT NULL ,
150 | [REPEAT_INTERVAL] [BIGINT] NOT NULL ,
151 | [TIMES_TRIGGERED] [INTEGER] NOT NULL
152 | ) ON [PRIMARY]
153 | GO
154 |
155 | CREATE TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] (
156 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
157 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
158 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
159 | [STR_PROP_1] [NVARCHAR] (512) NULL,
160 | [STR_PROP_2] [NVARCHAR] (512) NULL,
161 | [STR_PROP_3] [NVARCHAR] (512) NULL,
162 | [INT_PROP_1] [INT] NULL,
163 | [INT_PROP_2] [INT] NULL,
164 | [LONG_PROP_1] [BIGINT] NULL,
165 | [LONG_PROP_2] [BIGINT] NULL,
166 | [DEC_PROP_1] [NUMERIC] (13,4) NULL,
167 | [DEC_PROP_2] [NUMERIC] (13,4) NULL,
168 | [BOOL_PROP_1] BIT NULL,
169 | [BOOL_PROP_2] BIT NULL,
170 | ) ON [PRIMARY]
171 | GO
172 |
173 | CREATE TABLE [dbo].[QRTZ_BLOB_TRIGGERS] (
174 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
175 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
176 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
177 | [BLOB_DATA] [IMAGE] NULL
178 | ) ON [PRIMARY]
179 | GO
180 |
181 | CREATE TABLE [dbo].[QRTZ_TRIGGERS] (
182 | [SCHED_NAME] [NVARCHAR] (100) NOT NULL ,
183 | [TRIGGER_NAME] [NVARCHAR] (150) NOT NULL ,
184 | [TRIGGER_GROUP] [NVARCHAR] (150) NOT NULL ,
185 | [JOB_NAME] [NVARCHAR] (150) NOT NULL ,
186 | [JOB_GROUP] [NVARCHAR] (150) NOT NULL ,
187 | [DESCRIPTION] [NVARCHAR] (250) NULL ,
188 | [NEXT_FIRE_TIME] [BIGINT] NULL ,
189 | [PREV_FIRE_TIME] [BIGINT] NULL ,
190 | [PRIORITY] [INTEGER] NULL ,
191 | [TRIGGER_STATE] [NVARCHAR] (16) NOT NULL ,
192 | [TRIGGER_TYPE] [NVARCHAR] (8) NOT NULL ,
193 | [START_TIME] [BIGINT] NOT NULL ,
194 | [END_TIME] [BIGINT] NULL ,
195 | [CALENDAR_NAME] [NVARCHAR] (200) NULL ,
196 | [MISFIRE_INSTR] [INTEGER] NULL ,
197 | [JOB_DATA] [IMAGE] NULL
198 | ) ON [PRIMARY]
199 | GO
200 |
201 | ALTER TABLE [dbo].[QRTZ_CALENDARS] WITH NOCHECK ADD
202 | CONSTRAINT [PK_QRTZ_CALENDARS] PRIMARY KEY CLUSTERED
203 | (
204 | [SCHED_NAME],
205 | [CALENDAR_NAME]
206 | ) ON [PRIMARY]
207 | GO
208 |
209 | ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] WITH NOCHECK ADD
210 | CONSTRAINT [PK_QRTZ_CRON_TRIGGERS] PRIMARY KEY CLUSTERED
211 | (
212 | [SCHED_NAME],
213 | [TRIGGER_NAME],
214 | [TRIGGER_GROUP]
215 | ) ON [PRIMARY]
216 | GO
217 |
218 | ALTER TABLE [dbo].[QRTZ_FIRED_TRIGGERS] WITH NOCHECK ADD
219 | CONSTRAINT [PK_QRTZ_FIRED_TRIGGERS] PRIMARY KEY CLUSTERED
220 | (
221 | [SCHED_NAME],
222 | [ENTRY_ID]
223 | ) ON [PRIMARY]
224 | GO
225 |
226 | ALTER TABLE [dbo].[QRTZ_PAUSED_TRIGGER_GRPS] WITH NOCHECK ADD
227 | CONSTRAINT [PK_QRTZ_PAUSED_TRIGGER_GRPS] PRIMARY KEY CLUSTERED
228 | (
229 | [SCHED_NAME],
230 | [TRIGGER_GROUP]
231 | ) ON [PRIMARY]
232 | GO
233 |
234 | ALTER TABLE [dbo].[QRTZ_SCHEDULER_STATE] WITH NOCHECK ADD
235 | CONSTRAINT [PK_QRTZ_SCHEDULER_STATE] PRIMARY KEY CLUSTERED
236 | (
237 | [SCHED_NAME],
238 | [INSTANCE_NAME]
239 | ) ON [PRIMARY]
240 | GO
241 |
242 | ALTER TABLE [dbo].[QRTZ_LOCKS] WITH NOCHECK ADD
243 | CONSTRAINT [PK_QRTZ_LOCKS] PRIMARY KEY CLUSTERED
244 | (
245 | [SCHED_NAME],
246 | [LOCK_NAME]
247 | ) ON [PRIMARY]
248 | GO
249 |
250 | ALTER TABLE [dbo].[QRTZ_JOB_DETAILS] WITH NOCHECK ADD
251 | CONSTRAINT [PK_QRTZ_JOB_DETAILS] PRIMARY KEY CLUSTERED
252 | (
253 | [SCHED_NAME],
254 | [JOB_NAME],
255 | [JOB_GROUP]
256 | ) ON [PRIMARY]
257 | GO
258 |
259 | ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] WITH NOCHECK ADD
260 | CONSTRAINT [PK_QRTZ_SIMPLE_TRIGGERS] PRIMARY KEY CLUSTERED
261 | (
262 | [SCHED_NAME],
263 | [TRIGGER_NAME],
264 | [TRIGGER_GROUP]
265 | ) ON [PRIMARY]
266 | GO
267 |
268 | ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] WITH NOCHECK ADD
269 | CONSTRAINT [PK_QRTZ_SIMPROP_TRIGGERS] PRIMARY KEY CLUSTERED
270 | (
271 | [SCHED_NAME],
272 | [TRIGGER_NAME],
273 | [TRIGGER_GROUP]
274 | ) ON [PRIMARY]
275 | GO
276 |
277 | ALTER TABLE [dbo].[QRTZ_TRIGGERS] WITH NOCHECK ADD
278 | CONSTRAINT [PK_QRTZ_TRIGGERS] PRIMARY KEY CLUSTERED
279 | (
280 | [SCHED_NAME],
281 | [TRIGGER_NAME],
282 | [TRIGGER_GROUP]
283 | ) ON [PRIMARY]
284 | GO
285 |
286 | ALTER TABLE [dbo].[QRTZ_CRON_TRIGGERS] ADD
287 | CONSTRAINT [FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
288 | (
289 | [SCHED_NAME],
290 | [TRIGGER_NAME],
291 | [TRIGGER_GROUP]
292 | ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
293 | [SCHED_NAME],
294 | [TRIGGER_NAME],
295 | [TRIGGER_GROUP]
296 | ) ON DELETE CASCADE
297 | GO
298 |
299 | ALTER TABLE [dbo].[QRTZ_SIMPLE_TRIGGERS] ADD
300 | CONSTRAINT [FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
301 | (
302 | [SCHED_NAME],
303 | [TRIGGER_NAME],
304 | [TRIGGER_GROUP]
305 | ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
306 | [SCHED_NAME],
307 | [TRIGGER_NAME],
308 | [TRIGGER_GROUP]
309 | ) ON DELETE CASCADE
310 | GO
311 |
312 | ALTER TABLE [dbo].[QRTZ_SIMPROP_TRIGGERS] ADD
313 | CONSTRAINT [FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS] FOREIGN KEY
314 | (
315 | [SCHED_NAME],
316 | [TRIGGER_NAME],
317 | [TRIGGER_GROUP]
318 | ) REFERENCES [dbo].[QRTZ_TRIGGERS] (
319 | [SCHED_NAME],
320 | [TRIGGER_NAME],
321 | [TRIGGER_GROUP]
322 | ) ON DELETE CASCADE
323 | GO
324 |
325 | ALTER TABLE [dbo].[QRTZ_TRIGGERS] ADD
326 | CONSTRAINT [FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS] FOREIGN KEY
327 | (
328 | [SCHED_NAME],
329 | [JOB_NAME],
330 | [JOB_GROUP]
331 | ) REFERENCES [dbo].[QRTZ_JOB_DETAILS] (
332 | [SCHED_NAME],
333 | [JOB_NAME],
334 | [JOB_GROUP]
335 | )
336 | GO
337 |
338 | CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
339 | CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP)
340 | CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME)
341 | CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
342 | CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE)
343 | CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE)
344 | CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE)
345 | CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME)
346 | CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME)
347 | CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME)
348 | CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE)
349 | CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE)
350 |
351 | CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME)
352 | CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY)
353 | CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP)
354 | CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP)
355 | CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
356 | CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP)
357 | GO
--------------------------------------------------------------------------------
/src/.nuget/NuGet.Config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/.nuget/NuGet.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildProjectDirectory)\..\
5 |
6 |
7 | true
8 |
9 |
10 | false
11 |
12 |
13 | false
14 |
15 |
16 | true
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
27 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
28 |
29 |
30 |
31 |
32 | $(SolutionDir).nuget
33 | packages.config
34 |
35 |
36 |
37 |
38 | $(NuGetToolsPath)\nuget.exe
39 | @(PackageSource)
40 |
41 | "$(NuGetExePath)"
42 | mono --runtime=v4.0.30319 $(NuGetExePath)
43 |
44 | $(TargetDir.Trim('\\'))
45 |
46 | -RequireConsent
47 |
48 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "
49 | $(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols
50 |
51 |
52 |
53 | RestorePackages;
54 | $(ResolveReferencesDependsOn);
55 |
56 |
57 |
58 |
59 | $(BuildDependsOn);
60 | BuildPackage;
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
144 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/src/.nuget/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/MassTransit.Quartz.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.31101.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassTransit.QuartzIntegration", "MassTransit.QuartzIntegration\MassTransit.QuartzIntegration.csproj", "{2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{C9CDA928-0CFE-4861-BA77-2BBC79981109}"
9 | ProjectSection(SolutionItems) = preProject
10 | .nuget\NuGet.Config = .nuget\NuGet.Config
11 | .nuget\NuGet.exe = .nuget\NuGet.exe
12 | .nuget\NuGet.targets = .nuget\NuGet.targets
13 | .nuget\packages.config = .nuget\packages.config
14 | EndProjectSection
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassTransit.Scheduling", "MassTransit.Scheduling\MassTransit.Scheduling.csproj", "{863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassTransit.QuartzIntegration.Tests", "MassTransit.QuartzIntegration.Tests\MassTransit.QuartzIntegration.Tests.csproj", "{CC243B02-0542-48CB-B175-C8035075E376}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MassTransit.QuartzService", "MassTransit.QuartzService\MassTransit.QuartzService.csproj", "{989BA511-C126-4C88-A74B-BAD83DF2291B}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Debug|Mixed Platforms = Debug|Mixed Platforms
26 | Debug|x86 = Debug|x86
27 | Release|Any CPU = Release|Any CPU
28 | Release|Mixed Platforms = Release|Mixed Platforms
29 | Release|x86 = Release|x86
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
35 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
36 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Debug|x86.ActiveCfg = Debug|Any CPU
37 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Release|Any CPU.ActiveCfg = Release|Any CPU
38 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Release|Any CPU.Build.0 = Release|Any CPU
39 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
40 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Release|Mixed Platforms.Build.0 = Release|Any CPU
41 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}.Release|x86.ActiveCfg = Release|Any CPU
42 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
45 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
46 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Debug|x86.ActiveCfg = Debug|Any CPU
47 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
50 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Release|Mixed Platforms.Build.0 = Release|Any CPU
51 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}.Release|x86.ActiveCfg = Release|Any CPU
52 | {CC243B02-0542-48CB-B175-C8035075E376}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {CC243B02-0542-48CB-B175-C8035075E376}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {CC243B02-0542-48CB-B175-C8035075E376}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
55 | {CC243B02-0542-48CB-B175-C8035075E376}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
56 | {CC243B02-0542-48CB-B175-C8035075E376}.Debug|x86.ActiveCfg = Debug|Any CPU
57 | {CC243B02-0542-48CB-B175-C8035075E376}.Release|Any CPU.ActiveCfg = Release|Any CPU
58 | {CC243B02-0542-48CB-B175-C8035075E376}.Release|Any CPU.Build.0 = Release|Any CPU
59 | {CC243B02-0542-48CB-B175-C8035075E376}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
60 | {CC243B02-0542-48CB-B175-C8035075E376}.Release|Mixed Platforms.Build.0 = Release|Any CPU
61 | {CC243B02-0542-48CB-B175-C8035075E376}.Release|x86.ActiveCfg = Release|Any CPU
62 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|Any CPU.Build.0 = Debug|Any CPU
64 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|Mixed Platforms.ActiveCfg = Debug|x86
65 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|Mixed Platforms.Build.0 = Debug|x86
66 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|x86.ActiveCfg = Debug|x86
67 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Debug|x86.Build.0 = Debug|x86
68 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|Any CPU.ActiveCfg = Release|Any CPU
69 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|Any CPU.Build.0 = Release|Any CPU
70 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
71 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|Mixed Platforms.Build.0 = Release|Any CPU
72 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|x86.ActiveCfg = Release|x86
73 | {989BA511-C126-4C88-A74B-BAD83DF2291B}.Release|x86.Build.0 = Release|x86
74 | EndGlobalSection
75 | GlobalSection(SolutionProperties) = preSolution
76 | HideSolutionNode = FALSE
77 | EndGlobalSection
78 | EndGlobal
79 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/ContextSetup.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration.Tests
14 | {
15 | using Log4NetIntegration.Logging;
16 | using NUnit.Framework;
17 | using log4net;
18 |
19 |
20 | [SetUpFixture]
21 | public class ContextSetup
22 | {
23 | [SetUp]
24 | public void Before_any_tests()
25 | {
26 | Log4NetLogger.Use("log4net.config");
27 | }
28 |
29 | [TearDown]
30 | public void After_all_tests()
31 | {
32 | LogManager.Shutdown();
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/JobDetail_Specs.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzIntegration.Tests
2 | {
3 | using System.Threading;
4 | using Magnum.Extensions;
5 | using NUnit.Framework;
6 | using Quartz;
7 | using Quartz.Impl;
8 | using Quartz.Simpl;
9 |
10 |
11 | [TestFixture]
12 | public class When_scheduling_a_job_using_quartz
13 | {
14 |
15 | [Test]
16 | public void Should_return_the_properties()
17 | {
18 | var factory = new StdSchedulerFactory();
19 | var scheduler = factory.GetScheduler();
20 | scheduler.Start();
21 |
22 | IJobDetail jobDetail = JobBuilder.Create()
23 | .UsingJobData("Body", "By Jake")
24 | .Build();
25 |
26 | ITrigger trigger = TriggerBuilder.Create()
27 | .ForJob(jobDetail)
28 | .StartAt(1.Seconds().FromUtcNow())
29 | .Build();
30 |
31 | scheduler.ScheduleJob(jobDetail, trigger);
32 |
33 | Assert.IsTrue(MyJob.Signaled.WaitOne(Utils.Timeout));
34 |
35 | Assert.AreEqual("By Jake", MyJob.SignaledBody);
36 | }
37 |
38 | [Test]
39 | public void Should_return_the_properties_with_custom_factory()
40 | {
41 | var factory = new StdSchedulerFactory();
42 | var scheduler = factory.GetScheduler();
43 | scheduler.JobFactory = new MassTransitJobFactory(null);
44 | scheduler.Start();
45 |
46 | IJobDetail jobDetail = JobBuilder.Create()
47 | .UsingJobData("Body", "By Jake")
48 | .Build();
49 |
50 | ITrigger trigger = TriggerBuilder.Create()
51 | .ForJob(jobDetail)
52 | .StartAt(1.Seconds().FromUtcNow())
53 | .Build();
54 |
55 | scheduler.ScheduleJob(jobDetail, trigger);
56 |
57 | Assert.IsTrue(MyJob.Signaled.WaitOne(Utils.Timeout));
58 |
59 | Assert.AreEqual("By Jake", MyJob.SignaledBody);
60 | }
61 |
62 |
63 | class MyJob :
64 | IJob
65 | {
66 | public static ManualResetEvent Signaled { get; private set; }
67 | public static string SignaledBody { get; private set; }
68 |
69 | static MyJob()
70 | {
71 | Signaled = new ManualResetEvent(false);
72 | }
73 |
74 | public void Execute(IJobExecutionContext context)
75 | {
76 | SignaledBody = Body;
77 | Signaled.Set();
78 | }
79 |
80 | public string Body { get; set; }
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/MassTransit.QuartzIntegration.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {CC243B02-0542-48CB-B175-C8035075E376}
9 | Library
10 | Properties
11 | MassTransit.QuartzIntegration.Tests
12 | MassTransit.QuartzIntegration.Tests
13 | v4.0
14 | 512
15 | ..\
16 | true
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll
38 |
39 |
40 | ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll
41 |
42 |
43 | False
44 | ..\packages\Common.Logging.Log4Net1211.3.0.0\lib\net40\Common.Logging.Log4Net1211.dll
45 |
46 |
47 | False
48 | ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll
49 |
50 |
51 | False
52 | ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll
53 |
54 |
55 | ..\packages\MassTransit.2.10.2\lib\net40\MassTransit.dll
56 | True
57 |
58 |
59 | ..\packages\MassTransit.Log4Net.2.10.2\lib\net40\MassTransit.Log4NetIntegration.dll
60 | True
61 |
62 |
63 | ..\packages\MassTransit.RabbitMQ.2.10.2\lib\net40\MassTransit.Transports.RabbitMq.dll
64 | True
65 |
66 |
67 | False
68 | ..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll
69 |
70 |
71 | False
72 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll
73 |
74 |
75 | ..\packages\Quartz.2.3.2\lib\net40\Quartz.dll
76 |
77 |
78 | ..\packages\RabbitMQ.Client.3.4.3\lib\net35\RabbitMQ.Client.dll
79 |
80 |
81 |
82 |
83 |
84 |
85 | SolutionVersion.cs
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | Designer
98 |
99 |
100 | PreserveNewest
101 |
102 |
103 | Designer
104 |
105 |
106 |
107 |
108 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}
109 | MassTransit.QuartzIntegration
110 |
111 |
112 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}
113 | MassTransit.Scheduling
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
128 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/PastEvent_Specs.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzIntegration.Tests
2 | {
3 | using System;
4 | using System.Threading;
5 | using Magnum.Extensions;
6 | using NUnit.Framework;
7 | using Quartz;
8 | using Quartz.Impl;
9 | using Scheduling;
10 |
11 |
12 | [TestFixture]
13 | public class Specifying_an_event_in_the_past
14 | {
15 | [Test]
16 | public void Should_properly_send_the_message()
17 | {
18 | _bus.ScheduleMessage((-1).Hours().FromUtcNow(), new A { Name = "Joe" }, x =>
19 | {
20 | x.SetHeader("TestHeader", "Test");
21 | });
22 |
23 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
24 |
25 | Assert.IsTrue(_received.Headers["TestHeader"].Equals("Test"));
26 | }
27 |
28 |
29 | class A
30 | {
31 | public string Name { get; set; }
32 | }
33 |
34 | IScheduler _scheduler;
35 | IServiceBus _bus;
36 | ManualResetEvent _receivedA;
37 | IConsumeContext _received;
38 |
39 | [TestFixtureSetUp]
40 | public void Setup_quartz_service()
41 | {
42 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
43 | _scheduler = schedulerFactory.GetScheduler();
44 |
45 | _receivedA = new ManualResetEvent(false);
46 |
47 | _bus = ServiceBusFactory.New(x =>
48 | {
49 | x.ReceiveFrom("loopback://localhost/quartz");
50 | x.UseJsonSerializer();
51 |
52 | x.Subscribe(s =>
53 | {
54 | s.Handler((msg, context) =>
55 | {
56 | _received = msg;
57 | _receivedA.Set();
58 | });
59 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
60 | });
61 | });
62 |
63 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
64 | _scheduler.Start();
65 | }
66 |
67 | [TestFixtureTearDown]
68 | public void Teardown_quartz_service()
69 | {
70 | if (_scheduler != null)
71 | _scheduler.Standby();
72 | if (_bus != null)
73 | _bus.Dispose();
74 | if (_scheduler != null)
75 | _scheduler.Shutdown();
76 | }
77 | }
78 |
79 |
80 | [TestFixture, Explicit]
81 | public class Sending_past_events_to_quartz
82 | {
83 | [Test]
84 | public void Should_properly_send_the_message()
85 | {
86 | _bus.ScheduleMessage((-1).Minutes().FromUtcNow(), new A { Name = "Joe" }, x =>
87 | {
88 | x.SetHeader("TestHeader", "Test");
89 | });
90 |
91 | Assert.IsTrue(_receivedA.WaitOne(TimeSpan.FromMinutes(1)), "Message A not handled");
92 |
93 | Assert.IsTrue(_received.Headers["TestHeader"].Equals("Test"));
94 | }
95 |
96 | [Test]
97 | public void Should_not_handle_now()
98 | {
99 | _bus.ScheduleMessage(DateTime.UtcNow, new A { Name = "Joe" }, x =>
100 | {
101 | x.SetHeader("TestHeader", "Test");
102 | });
103 |
104 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
105 |
106 | Assert.IsTrue(_received.Headers["TestHeader"].Equals("Test"));
107 | }
108 |
109 | [Test]
110 | public void Should_send_a_future_message()
111 | {
112 | _bus.ScheduleMessage((1).Seconds().FromUtcNow(), new A { Name = "Joe" }, x =>
113 | {
114 | x.SetHeader("TestHeader", "Test");
115 | });
116 |
117 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
118 |
119 | Assert.IsTrue(_received.Headers["TestHeader"].Equals("Test"));
120 | }
121 |
122 |
123 | class A
124 | {
125 | public string Name { get; set; }
126 | }
127 |
128 | IServiceBus _bus;
129 | ManualResetEvent _receivedA;
130 | IConsumeContext _received;
131 |
132 | [TestFixtureSetUp]
133 | public void Setup_quartz_service()
134 | {
135 | _receivedA = new ManualResetEvent(false);
136 |
137 | _bus = ServiceBusFactory.New(x =>
138 | {
139 | x.ReceiveFrom("rabbitmq://localhost/test_quartz_client");
140 | x.UseJsonSerializer();
141 | x.UseRabbitMq();
142 |
143 | x.Subscribe(s =>
144 | {
145 | s.Handler((msg, context) =>
146 | {
147 | _received = msg;
148 | _receivedA.Set();
149 | });
150 | });
151 | });
152 |
153 | }
154 |
155 | [TestFixtureTearDown]
156 | public void Teardown_quartz_service()
157 | {
158 | if (_bus != null)
159 | _bus.Dispose();
160 | }
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/Service_Specs.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration.Tests
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 | using System.Linq;
18 | using System.Threading;
19 | using Magnum.Extensions;
20 | using NUnit.Framework;
21 | using Quartz;
22 | using Quartz.Impl;
23 | using Scheduling;
24 |
25 |
26 | [TestFixture]
27 | public class Using_the_quartz_service_with_json
28 | {
29 | [Test]
30 | public void Should_startup_properly()
31 | {
32 | _bus.ScheduleMessage(1.Seconds().FromUtcNow(), new A {Name = "Joe"});
33 |
34 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
35 | Assert.IsTrue(_receivedIA.WaitOne(Utils.Timeout), "Message IA not handled");
36 | }
37 |
38 |
39 | class A : IA
40 | {
41 | public string Name { get; set; }
42 | }
43 |
44 |
45 | class IA
46 | {
47 | string Id { get; set; }
48 | }
49 |
50 |
51 | IScheduler _scheduler;
52 | IServiceBus _bus;
53 | ManualResetEvent _receivedA;
54 | ManualResetEvent _receivedIA;
55 |
56 | [TestFixtureSetUp]
57 | public void Setup_quartz_service()
58 | {
59 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
60 | _scheduler = schedulerFactory.GetScheduler();
61 |
62 | _receivedA = new ManualResetEvent(false);
63 | _receivedIA = new ManualResetEvent(false);
64 |
65 | _bus = ServiceBusFactory.New(x =>
66 | {
67 | x.ReceiveFrom("loopback://localhost/quartz");
68 | x.UseJsonSerializer();
69 |
70 | x.Subscribe(s =>
71 | {
72 | s.Handler(msg => _receivedA.Set());
73 | s.Handler(msg => _receivedIA.Set());
74 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
75 | });
76 | });
77 |
78 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
79 | _scheduler.Start();
80 | }
81 |
82 | [TestFixtureTearDown]
83 | public void Teardown_quartz_service()
84 | {
85 | if (_scheduler != null)
86 | _scheduler.Standby();
87 | if (_bus != null)
88 | _bus.Dispose();
89 | if (_scheduler != null)
90 | _scheduler.Shutdown();
91 | }
92 | }
93 |
94 |
95 | [TestFixture]
96 | public class Using_the_quartz_service_with_xml
97 | {
98 | [Test]
99 | public void Should_startup_properly()
100 | {
101 | _bus.ScheduleMessage(1.Seconds().FromUtcNow(), new A {Name = "Joe"});
102 |
103 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
104 | Assert.IsTrue(_receivedIA.WaitOne(Utils.Timeout), "Message IA not handled");
105 | }
106 |
107 |
108 | class A : IA
109 | {
110 | public string Name { get; set; }
111 | }
112 |
113 |
114 | class IA
115 | {
116 | string Id { get; set; }
117 | }
118 |
119 |
120 | IScheduler _scheduler;
121 | IServiceBus _bus;
122 | ManualResetEvent _receivedA;
123 | ManualResetEvent _receivedIA;
124 |
125 | [TestFixtureSetUp]
126 | public void Setup_quartz_service()
127 | {
128 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
129 | _scheduler = schedulerFactory.GetScheduler();
130 |
131 | _receivedA = new ManualResetEvent(false);
132 | _receivedIA = new ManualResetEvent(false);
133 |
134 | _bus = ServiceBusFactory.New(x =>
135 | {
136 | x.ReceiveFrom("loopback://localhost/quartz");
137 | x.UseXmlSerializer();
138 |
139 | x.Subscribe(s =>
140 | {
141 | s.Handler(msg => _receivedA.Set());
142 | s.Handler(msg => _receivedIA.Set());
143 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
144 | });
145 | });
146 |
147 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
148 | _scheduler.Start();
149 | }
150 |
151 | [TestFixtureTearDown]
152 | public void Teardown_quartz_service()
153 | {
154 | if (_scheduler != null)
155 | _scheduler.Standby();
156 | if (_bus != null)
157 | _bus.Dispose();
158 | if (_scheduler != null)
159 | _scheduler.Shutdown();
160 | }
161 | }
162 |
163 |
164 | [TestFixture]
165 | public class Using_the_quartz_service_and_cancelling
166 | {
167 | [Test]
168 | public void Should_cancel_the_scheduled_message()
169 | {
170 | ScheduledMessage scheduledMessage = _bus.ScheduleMessage(8.Seconds().FromUtcNow(),
171 | new A {Name = "Joe"});
172 |
173 | _bus.CancelScheduledMessage(scheduledMessage);
174 |
175 | Assert.IsFalse(_receivedA.WaitOne(Utils.Timeout), "Message A handled");
176 | Assert.IsFalse(_receivedIA.WaitOne(1.Seconds()), "Message IA handled");
177 | }
178 |
179 |
180 | class A : IA
181 | {
182 | public string Name { get; set; }
183 | }
184 |
185 |
186 | class IA
187 | {
188 | string Id { get; set; }
189 | }
190 |
191 |
192 | IScheduler _scheduler;
193 | IServiceBus _bus;
194 | ManualResetEvent _receivedA;
195 | ManualResetEvent _receivedIA;
196 |
197 | [TestFixtureSetUp]
198 | public void Setup_quartz_service()
199 | {
200 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
201 | _scheduler = schedulerFactory.GetScheduler();
202 |
203 | _receivedA = new ManualResetEvent(false);
204 | _receivedIA = new ManualResetEvent(false);
205 |
206 | _bus = ServiceBusFactory.New(x =>
207 | {
208 | x.ReceiveFrom("loopback://localhost/quartz");
209 | x.UseXmlSerializer();
210 | x.SetConcurrentConsumerLimit(1);
211 |
212 | x.Subscribe(s =>
213 | {
214 | s.Handler(msg => _receivedA.Set());
215 | s.Handler(msg => _receivedIA.Set());
216 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
217 | s.Consumer(() => new CancelScheduledMessageConsumer(_scheduler));
218 | });
219 | });
220 |
221 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
222 | _scheduler.Start();
223 | }
224 |
225 | [TestFixtureTearDown]
226 | public void Teardown_quartz_service()
227 | {
228 | if (_scheduler != null)
229 | _scheduler.Standby();
230 | if (_bus != null)
231 | _bus.Dispose();
232 | if (_scheduler != null)
233 | _scheduler.Shutdown();
234 | }
235 | }
236 |
237 | [TestFixture]
238 | public class Using_the_quartz_service_with_headers
239 | {
240 | [Test]
241 | public void Should_not_loose_headers()
242 | {
243 | var headers = new KeyValuePair[0];
244 | _bus.SubscribeContextHandler(ctx =>
245 | {
246 | headers = ctx.Headers.ToArray();
247 | _receivedA.Set();
248 | });
249 |
250 | _bus.ScheduleMessage(1.Seconds().FromUtcNow(), new A { Name = "Joe" },
251 | ctx =>
252 | {
253 | ctx.SetHeader("ATest", "AValue");
254 | });
255 |
256 | Assert.IsTrue(_receivedA.WaitOne(Utils.Timeout), "Message A not handled");
257 | Assert.IsNotEmpty(headers, "No Headers were sent");
258 | Assert.AreEqual("AValue", headers.First(h => h.Key == "ATest").Value);
259 | }
260 |
261 |
262 |
263 | class A
264 | {
265 | public string Name { get; set; }
266 | }
267 |
268 |
269 |
270 | IScheduler _scheduler;
271 | IServiceBus _bus;
272 | ManualResetEvent _receivedA;
273 |
274 | [TestFixtureSetUp]
275 | public void Setup_quartz_service()
276 | {
277 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
278 | _scheduler = schedulerFactory.GetScheduler();
279 |
280 | _receivedA = new ManualResetEvent(false);
281 |
282 | _bus = ServiceBusFactory.New(x =>
283 | {
284 | x.ReceiveFrom("loopback://localhost/quartz");
285 | x.UseJsonSerializer();
286 |
287 | x.Subscribe(s =>
288 | {
289 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
290 | });
291 | });
292 |
293 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
294 | _scheduler.Start();
295 | }
296 |
297 | [TestFixtureTearDown]
298 | public void Teardown_quartz_service()
299 | {
300 | if (_scheduler != null)
301 | _scheduler.Standby();
302 | if (_bus != null)
303 | _bus.Dispose();
304 | if (_scheduler != null)
305 | _scheduler.Shutdown();
306 | }
307 | }
308 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/Syntax_Specs.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration.Tests
14 | {
15 | using Magnum.Extensions;
16 | using NUnit.Framework;
17 | using Scheduling;
18 |
19 |
20 | [TestFixture]
21 | public class Syntax_Specs
22 | {
23 | [Test]
24 | public void Should_have_a_clean_syntax()
25 | {
26 | IServiceBus bus = ServiceBusFactory.New(x => x.ReceiveFrom("loopback://localhost/client"));
27 | using (bus)
28 | {
29 | ScheduledMessage scheduledMessage = bus.ScheduleMessage(5.Seconds().FromNow(), new A());
30 |
31 | Assert.IsNotNull(scheduledMessage);
32 | }
33 | }
34 |
35 |
36 | class A
37 | {
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/Utils.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration.Tests
14 | {
15 | using System;
16 | using System.Diagnostics;
17 |
18 |
19 | public static class Utils
20 | {
21 | public static TimeSpan Timeout
22 | {
23 | get
24 | {
25 | if (Debugger.IsAttached)
26 | return TimeSpan.FromMinutes(10);
27 |
28 | return TimeSpan.FromSeconds(8);
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/log4net.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | q
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/CancelScheduledMessageConsumer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using Logging;
16 | using Quartz;
17 | using Scheduling;
18 |
19 |
20 | public class CancelScheduledMessageConsumer :
21 | Consumes.Context
22 | {
23 | static readonly ILog _log = Logger.Get();
24 | readonly IScheduler _scheduler;
25 |
26 | public CancelScheduledMessageConsumer(IScheduler scheduler)
27 | {
28 | _scheduler = scheduler;
29 | }
30 |
31 | public void Consume(IConsumeContext context)
32 | {
33 | bool unscheduledJob = _scheduler.UnscheduleJob(new TriggerKey(context.Message.TokenId.ToString("N")));
34 |
35 | if (_log.IsDebugEnabled)
36 | {
37 | if (unscheduledJob)
38 | {
39 | _log.DebugFormat("CancelScheduledMessage: {0} at {1}", context.Message.TokenId,
40 | context.Message.Timestamp);
41 | }
42 | else
43 | _log.DebugFormat("CancelScheduledMessage: no message found {0}", context.Message.TokenId);
44 | }
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/CancelScheduledTimeoutConsumer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using Logging;
16 | using Quartz;
17 | using Services.Timeout.Messages;
18 |
19 |
20 | public class CancelScheduledTimeoutConsumer :
21 | Consumes.Context
22 | {
23 | static readonly ILog _log = Logger.Get();
24 | readonly IScheduler _scheduler;
25 |
26 | public CancelScheduledTimeoutConsumer(IScheduler scheduler)
27 | {
28 | _scheduler = scheduler;
29 | }
30 |
31 | public void Consume(IConsumeContext context)
32 | {
33 | string triggerKey = context.Message.CorrelationId.ToString("N") + context.Message.Tag;
34 |
35 | bool unscheduledJob = _scheduler.UnscheduleJob(new TriggerKey(triggerKey));
36 |
37 | if (_log.IsDebugEnabled)
38 | {
39 | if (unscheduledJob)
40 | {
41 | _log.DebugFormat("CancelScheduledMessage: {0}", triggerKey);
42 |
43 | context.Bus.Publish(new TimeoutCancelled
44 | {
45 | CorrelationId = context.Message.CorrelationId,
46 | Tag = context.Message.Tag,
47 | });
48 | }
49 | else
50 | _log.DebugFormat("CancelScheduledMessage: no message found {0}", triggerKey);
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/MassTransit.QuartzIntegration.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}
9 | Library
10 | Properties
11 | MassTransit.QuartzIntegration
12 | MassTransit.QuartzIntegration
13 | v4.0
14 | 512
15 | .\
16 | true
17 |
18 |
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 | ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll
38 |
39 |
40 | ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll
41 |
42 |
43 | False
44 | ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll
45 |
46 |
47 | ..\packages\MassTransit.2.10.2\lib\net40\MassTransit.dll
48 | True
49 |
50 |
51 | False
52 | ..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll
53 |
54 |
55 | ..\packages\Quartz.2.3.2\lib\net40\Quartz.dll
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | SolutionVersion.cs
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Designer
81 |
82 |
83 | Designer
84 |
85 |
86 |
87 |
88 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}
89 | MassTransit.Scheduling
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
104 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/MassTransitJobFactory.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using System.Globalization;
17 | using System.Linq;
18 | using System.Linq.Expressions;
19 | using System.Reflection;
20 | using Magnum.Caching;
21 | using Magnum.Extensions;
22 | using Magnum.Reflection;
23 | using Quartz;
24 | using Quartz.Spi;
25 |
26 |
27 | public class MassTransitJobFactory :
28 | IJobFactory
29 | {
30 | readonly IServiceBus _bus;
31 | readonly Cache _typeFactories;
32 |
33 | public MassTransitJobFactory(IServiceBus bus)
34 | {
35 | _bus = bus;
36 | _typeFactories = new GenericTypeCache(typeof(MassTransitJobFactory<>), type =>
37 | {
38 | Type genericType = typeof(MassTransitJobFactory<>).MakeGenericType(type);
39 |
40 | return (IJobFactory)Activator.CreateInstance(genericType, _bus);
41 | });
42 | }
43 |
44 | public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
45 | {
46 | IJobDetail jobDetail = bundle.JobDetail;
47 | if (jobDetail == null)
48 | throw new SchedulerException("JobDetail was null");
49 |
50 | Type type = jobDetail.JobType;
51 |
52 | return _typeFactories[type].NewJob(bundle, scheduler);
53 | }
54 |
55 | public void ReturnJob(IJob job)
56 | {
57 | }
58 | }
59 |
60 |
61 | public class MassTransitJobFactory :
62 | IJobFactory
63 | where T : IJob
64 | {
65 | readonly IServiceBus _bus;
66 | readonly Func _factory;
67 | readonly Cache> _propertyCache;
68 |
69 | public MassTransitJobFactory(IServiceBus bus)
70 | {
71 | _bus = bus;
72 | _factory = CreateConstructor();
73 |
74 | const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
75 |
76 | _propertyCache = new DictionaryCache>(typeof(T).GetProperties(Flags)
77 | .Where(x => x.GetGetMethod(true) != null)
78 | .Where(x => x.GetSetMethod(true) != null)
79 | .Select(x => new FastProperty(x, Flags))
80 | .ToDictionary(x => x.Property.Name));
81 | }
82 |
83 | public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
84 | {
85 | try
86 | {
87 | T job = _factory(_bus);
88 |
89 | var jobData = new JobDataMap();
90 | jobData.PutAll(scheduler.Context);
91 | jobData.PutAll(bundle.JobDetail.JobDataMap);
92 | jobData.PutAll(bundle.Trigger.JobDataMap);
93 |
94 | SetObjectProperties(job, jobData);
95 |
96 | return job;
97 | }
98 | catch (Exception ex)
99 | {
100 | var sex = new SchedulerException(string.Format(CultureInfo.InvariantCulture,
101 | "Problem instantiating class '{0}'", bundle.JobDetail.JobType.FullName), ex);
102 | throw sex;
103 | }
104 | }
105 |
106 | public void ReturnJob(IJob job)
107 | {
108 | }
109 |
110 | void SetObjectProperties(T job, JobDataMap jobData)
111 | {
112 | foreach (string key in jobData.Keys)
113 | {
114 | if (_propertyCache.Has(key))
115 | {
116 | FastProperty property = _propertyCache[key];
117 |
118 | object value = jobData[key];
119 |
120 | if (property.Property.PropertyType == typeof(Uri))
121 | value = new Uri(value.ToString());
122 |
123 | property.Set(job, value);
124 | }
125 | }
126 | }
127 |
128 | Func CreateConstructor()
129 | {
130 | ConstructorInfo ctor = typeof(T).GetConstructor(new[] {typeof(IServiceBus)});
131 | if (ctor != null)
132 | return CreateServiceBusConstructor(ctor);
133 |
134 | ctor = typeof(T).GetConstructor(Type.EmptyTypes);
135 | if (ctor != null)
136 | return CreateDefaultConstructor(ctor);
137 |
138 | throw new SchedulerException(string.Format(CultureInfo.InvariantCulture,
139 | "The job class does not have a supported constructor: {0}", typeof(T).ToShortTypeName()));
140 | }
141 |
142 | Func CreateDefaultConstructor(ConstructorInfo constructorInfo)
143 | {
144 | ParameterExpression bus = Expression.Parameter(typeof(IServiceBus), "bus");
145 | NewExpression @new = Expression.New(constructorInfo);
146 |
147 | return Expression.Lambda>(@new, bus).Compile();
148 | }
149 |
150 | Func CreateServiceBusConstructor(ConstructorInfo constructorInfo)
151 | {
152 | ParameterExpression bus = Expression.Parameter(typeof(IServiceBus), "bus");
153 | NewExpression @new = Expression.New(constructorInfo, bus);
154 |
155 | return Expression.Lambda>(@new, bus).Compile();
156 | }
157 | }
158 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduleMessageConsumer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 | using System.IO;
18 | using System.Linq;
19 | using System.Text;
20 | using System.Xml.Linq;
21 | using Logging;
22 | using Newtonsoft.Json;
23 | using Newtonsoft.Json.Linq;
24 | using Quartz;
25 | using Scheduling;
26 |
27 |
28 | public class ScheduleMessageConsumer :
29 | Consumes.Context
30 | {
31 | static readonly ILog _log = Logger.Get();
32 | readonly IScheduler _scheduler;
33 |
34 | public ScheduleMessageConsumer(IScheduler scheduler)
35 | {
36 | _scheduler = scheduler;
37 | }
38 |
39 | public void Consume(IConsumeContext context)
40 | {
41 | if (_log.IsDebugEnabled)
42 | {
43 | _log.DebugFormat("ScheduleMessage: {0} at {1}", context.Message.CorrelationId,
44 | context.Message.ScheduledTime);
45 | }
46 |
47 | string body;
48 | using (var ms = new MemoryStream())
49 | {
50 | context.BaseContext.CopyBodyTo(ms);
51 |
52 | body = Encoding.UTF8.GetString(ms.ToArray());
53 | }
54 |
55 | if (string.Compare(context.ContentType, "application/vnd.masstransit+json",
56 | StringComparison.OrdinalIgnoreCase)
57 | == 0)
58 | body = TranslateJsonBody(body, context.Message.Destination.ToString());
59 | else if (string.Compare(context.ContentType, "application/vnd.masstransit+xml",
60 | StringComparison.OrdinalIgnoreCase) == 0)
61 | body = TranslateXmlBody(body, context.Message.Destination.ToString());
62 | else
63 | throw new InvalidOperationException("Only JSON and XML messages can be scheduled");
64 |
65 | IJobDetail jobDetail = JobBuilder.Create()
66 | .RequestRecovery(true)
67 | .WithIdentity(context.Message.CorrelationId.ToString("N"))
68 | .UsingJobData("Destination", ToString(context.Message.Destination))
69 | .UsingJobData("ResponseAddress", ToString(context.ResponseAddress))
70 | .UsingJobData("FaultAddress", ToString(context.FaultAddress))
71 | .UsingJobData("Body", body)
72 | .UsingJobData("ContentType", context.ContentType)
73 | .UsingJobData("MessageId", context.MessageId)
74 | .UsingJobData("RequestId", context.RequestId)
75 | .UsingJobData("ConversationId", context.ConversationId)
76 | .UsingJobData("CorrelationId", context.CorrelationId)
77 | .UsingJobData("HeadersAsJson", JsonConvert.SerializeObject(context.Headers))
78 | .UsingJobData("ExpirationTime",
79 | context.ExpirationTime.HasValue ? context.ExpirationTime.Value.ToString() : "")
80 | .UsingJobData("Network", context.Network)
81 | .UsingJobData("RetryCount", context.RetryCount)
82 | .Build();
83 |
84 | ITrigger trigger = TriggerBuilder.Create()
85 | .ForJob(jobDetail)
86 | .StartAt(context.Message.ScheduledTime)
87 | .WithSchedule(SimpleScheduleBuilder.Create().WithMisfireHandlingInstructionFireNow())
88 | .WithIdentity(new TriggerKey(context.Message.CorrelationId.ToString("N")))
89 | .Build();
90 |
91 | _scheduler.ScheduleJob(jobDetail, trigger);
92 | }
93 |
94 | static string ToString(Uri uri)
95 | {
96 | if (uri == null)
97 | return "";
98 |
99 | return uri.ToString();
100 | }
101 |
102 |
103 | static string TranslateJsonBody(string body, string destination)
104 | {
105 | JObject envelope = JObject.Parse(body);
106 |
107 | envelope["destinationAddress"] = destination;
108 |
109 | JToken message = envelope["message"];
110 |
111 | JToken payload = message["payload"];
112 | JToken payloadType = message["payloadType"];
113 |
114 | envelope["message"] = payload;
115 | envelope["messageType"] = payloadType;
116 |
117 | return JsonConvert.SerializeObject(envelope, Formatting.Indented);
118 | }
119 |
120 | static string TranslateXmlBody(string body, string destination)
121 | {
122 | using (var reader = new StringReader(body))
123 | {
124 | XDocument document = XDocument.Load(reader);
125 |
126 | XElement envelope = (from e in document.Descendants("envelope") select e).Single();
127 |
128 | XElement destinationAddress = (from a in envelope.Descendants("destinationAddress") select a).Single();
129 |
130 | XElement message = (from m in envelope.Descendants("message") select m).Single();
131 | IEnumerable messageType = (from mt in envelope.Descendants("messageType") select mt);
132 |
133 | XElement payload = (from p in message.Descendants("payload") select p).Single();
134 | IEnumerable payloadType = (from pt in message.Descendants("payloadType") select pt);
135 |
136 | message.Remove();
137 | messageType.Remove();
138 |
139 | destinationAddress.Value = destination;
140 |
141 | message = new XElement("message");
142 | message.Add(payload.Descendants());
143 | envelope.Add(message);
144 |
145 | envelope.Add(payloadType.Select(x => new XElement("messageType", x.Value)));
146 |
147 | return document.ToString();
148 | }
149 | }
150 | }
151 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduleMessageJobBuilder.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using Quartz;
16 | using Scheduling;
17 |
18 |
19 | public interface ScheduleMessageJobBuilder
20 | {
21 | void Consume(IScheduler scheduler, IConsumeContext context);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduleMessageJobBuilderImpl.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using Quartz;
17 | using Scheduling;
18 |
19 |
20 | public class ScheduleMessageJobBuilderImpl :
21 | ScheduleMessageJobBuilder
22 | where T : class
23 | {
24 | public void Consume(IScheduler scheduler, IConsumeContext context)
25 | {
26 | IConsumeContext> consumeContext;
27 | if (context.TryGetContext(out consumeContext))
28 | {
29 |
30 | }
31 |
32 | throw new InvalidOperationException("The message context could not be mapped: {0}" + typeof(T));
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduleTimeoutConsumer.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using Logging;
17 | using Quartz;
18 | using Services.Timeout.Messages;
19 |
20 |
21 | public class ScheduleTimeoutConsumer :
22 | Consumes.Context
23 | {
24 | static readonly ILog _log = Logger.Get();
25 | readonly IScheduler _scheduler;
26 |
27 | public ScheduleTimeoutConsumer(IScheduler scheduler)
28 | {
29 | _scheduler = scheduler;
30 | }
31 |
32 | public void Consume(IConsumeContext context)
33 | {
34 | DateTime startTimeUtc = context.Message.TimeoutAt;
35 | if (startTimeUtc.Kind == DateTimeKind.Local)
36 | startTimeUtc = startTimeUtc.ToUniversalTime();
37 |
38 | if (_log.IsDebugEnabled)
39 | {
40 | _log.DebugFormat("ScheduleTimeout: {0}[{1} at {2}", context.Message.CorrelationId,
41 | context.Message.Tag,
42 | startTimeUtc);
43 | }
44 |
45 | string triggerKey = context.Message.CorrelationId.ToString("N") + context.Message.Tag;
46 |
47 | var key = new TriggerKey(triggerKey);
48 |
49 | IJobDetail jobDetail = JobBuilder.Create()
50 | .RequestRecovery(true)
51 | .WithIdentity(context.Message.CorrelationId.ToString("N"))
52 | .UsingJobData("Tag", context.Message.Tag)
53 | .UsingJobData("CorrelationId", context.Message.CorrelationId.ToString())
54 | .Build();
55 |
56 |
57 | ITrigger trigger = TriggerBuilder.Create()
58 | .ForJob(jobDetail)
59 | .StartAt(startTimeUtc)
60 | .WithIdentity(key)
61 | .Build();
62 |
63 | if (_scheduler.CheckExists(key))
64 | {
65 | _scheduler.RescheduleJob(key, trigger);
66 |
67 | context.Bus.Publish(new TimeoutRescheduled
68 | {
69 | CorrelationId = context.Message.CorrelationId,
70 | TimeoutAt = startTimeUtc,
71 | Tag = context.Message.Tag,
72 | });
73 | }
74 | else
75 | {
76 | _scheduler.ScheduleJob(jobDetail, trigger);
77 |
78 | context.Bus.Publish(new TimeoutScheduled
79 | {
80 | CorrelationId = context.Message.CorrelationId,
81 | TimeoutAt = startTimeUtc,
82 | Tag = context.Message.Tag,
83 | });
84 | }
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduledMessageContext.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 | using System.IO;
18 | using Context;
19 | using Serialization.Custom;
20 |
21 |
22 | public class ScheduledMessageContext :
23 | MessageContext,
24 | ISendContext
25 | {
26 | readonly string _body;
27 |
28 | public ScheduledMessageContext(string body)
29 | {
30 | _body = body;
31 | Id = NewId.NextGuid();
32 | DeclaringMessageType = typeof(ScheduledMessageContext);
33 | }
34 |
35 | public void SetWaitForAck(bool wait = true)
36 | {
37 | }
38 |
39 | public void SetDeliveryMode(DeliveryMode deliveryMode)
40 | {
41 | DeliveryMode = deliveryMode;
42 | }
43 |
44 | public void SerializeTo(Stream stream)
45 | {
46 | using (var nonClosingStream = new NonClosingStream(stream))
47 | using (var writer = new StreamWriter(nonClosingStream))
48 | {
49 | writer.Write(_body);
50 | }
51 | }
52 |
53 | public void SetHeaders(IEnumerable> headers)
54 | {
55 | foreach (var entry in headers)
56 | SetHeader(entry.Key, entry.Value);
57 | }
58 |
59 | public bool TryGetContext(out IBusPublishContext context)
60 | where T : class
61 | {
62 | context = null;
63 | return false;
64 | }
65 |
66 | public void NotifySend(IEndpointAddress address)
67 | {
68 | }
69 |
70 | public Guid Id { get; private set; }
71 | public Type DeclaringMessageType { get; private set; }
72 | public DeliveryMode DeliveryMode { get; private set; }
73 |
74 | public bool WaitForAck
75 | {
76 | get { return true; }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduledMessageJob.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 | using System.Globalization;
18 | using Logging;
19 | using Newtonsoft.Json;
20 | using Quartz;
21 |
22 |
23 | public class ScheduledMessageJob :
24 | IJob
25 | {
26 | static readonly ILog _log = Logger.Get();
27 |
28 | readonly IServiceBus _bus;
29 |
30 | public ScheduledMessageJob(IServiceBus bus)
31 | {
32 | _bus = bus;
33 | }
34 |
35 | public string Destination { get; set; }
36 |
37 | public string ExpirationTime { get; set; }
38 | public string ResponseAddress { get; set; }
39 | public string FaultAddress { get; set; }
40 | public string Body { get; set; }
41 |
42 | public string MessageId { get; set; }
43 | public string MessageType { get; set; }
44 | public string ContentType { get; set; }
45 | public string RequestId { get; set; }
46 | public string ConversationId { get; set; }
47 | public string CorrelationId { get; set; }
48 | public string Network { get; set; }
49 | public int RetryCount { get; set; }
50 | public string HeadersAsJson { get; set; }
51 |
52 | public void Execute(IJobExecutionContext context)
53 | {
54 | try
55 | {
56 | var destinationAddress = new Uri(Destination);
57 | Uri sourceAddress = _bus.Endpoint.Address.Uri;
58 |
59 | IEndpoint endpoint = _bus.GetEndpoint(destinationAddress);
60 |
61 | ISendContext messageContext = CreateMessageContext(sourceAddress, destinationAddress);
62 |
63 | endpoint.OutboundTransport.Send(messageContext);
64 | }
65 | catch (Exception ex)
66 | {
67 | string message = string.Format(CultureInfo.InvariantCulture,
68 | "An exception occurred sending message {0} to {1}", MessageType, Destination);
69 | _log.Error(message, ex);
70 |
71 | throw new JobExecutionException(message, ex);
72 | }
73 | }
74 |
75 |
76 | ISendContext CreateMessageContext(Uri sourceAddress, Uri destinationAddress)
77 | {
78 | var context = new ScheduledMessageContext(Body);
79 |
80 | context.SetDestinationAddress(destinationAddress);
81 | context.SetSourceAddress(sourceAddress);
82 | context.SetResponseAddress(ToUri(ResponseAddress));
83 | context.SetFaultAddress(ToUri(FaultAddress));
84 |
85 | SetHeaders(context);
86 | context.SetMessageId(MessageId);
87 | context.SetRequestId(RequestId);
88 | context.SetConversationId(ConversationId);
89 | context.SetCorrelationId(CorrelationId);
90 |
91 | if (!string.IsNullOrEmpty(ExpirationTime))
92 | context.SetExpirationTime(DateTime.Parse(ExpirationTime));
93 |
94 | context.SetNetwork(Network);
95 | context.SetRetryCount(RetryCount);
96 | context.SetContentType(ContentType);
97 |
98 | return context;
99 | }
100 |
101 | void SetHeaders(ScheduledMessageContext context)
102 | {
103 | if (string.IsNullOrEmpty(HeadersAsJson))
104 | return;
105 |
106 | var headers = JsonConvert.DeserializeObject>>(HeadersAsJson);
107 | context.SetHeaders(headers);
108 | }
109 |
110 | static Uri ToUri(string s)
111 | {
112 | if (string.IsNullOrEmpty(s))
113 | return null;
114 |
115 | return new Uri(s);
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/ScheduledTimeoutJob.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzIntegration
14 | {
15 | using System;
16 | using System.Globalization;
17 | using Logging;
18 | using Quartz;
19 | using Services.Timeout.Messages;
20 |
21 |
22 | public class ScheduledTimeoutJob :
23 | IJob
24 | {
25 | static readonly ILog _log = Logger.Get();
26 |
27 | readonly IServiceBus _bus;
28 |
29 | public ScheduledTimeoutJob(IServiceBus bus)
30 | {
31 | _bus = bus;
32 | }
33 |
34 |
35 | public string CorrelationId { get; set; }
36 | public int Tag { get; set; }
37 |
38 | public void Execute(IJobExecutionContext context)
39 | {
40 | try
41 | {
42 | _bus.Publish(new TimeoutExpired
43 | {
44 | CorrelationId = Guid.Parse(CorrelationId),
45 | Tag = Tag,
46 | });
47 | }
48 | catch (Exception ex)
49 | {
50 | string message = string.Format(CultureInfo.InvariantCulture,
51 | "An exception occurred publishing scheduled timeout {0}[{1}]", CorrelationId, Tag);
52 | _log.Error(message, ex);
53 |
54 | throw new JobExecutionException(message, ex);
55 | }
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/job_scheduling_data_2_0.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 | Root level node
12 |
13 |
14 |
15 |
16 |
17 | Commands to be executed before scheduling the jobs and triggers in this file.
18 |
19 |
20 |
21 |
22 | Directives to be followed while scheduling the jobs and triggers in this file.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Version of the XML Schema instance
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs.
47 |
48 |
49 |
50 |
51 | Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable.
52 |
53 |
54 |
55 |
56 | Delete the identified job if it exists (will also result in deleting all triggers related to it).
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable).
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur.
84 |
85 |
86 |
87 |
88 | If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced.
89 |
90 |
91 |
92 |
93 | If true trigger's start time is calculated based on earlier run time instead of fixed value. Trigger's start time must be undefined for this to work.
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Define a JobDetail
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | Define a JobDataMap
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | Define a JobDataMap entry
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | Define a Trigger
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | Common Trigger definitions
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | Define a SimpleTrigger
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | Define a CronTrigger
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | Define a DateIntervalTrigger
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 | Cron expression (see JavaDoc for examples)
220 |
221 | Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression!
222 |
223 | Regular expressions are not my strong point but I believe this is complete,
224 | with the caveat that order for expressions like 3-0 is not legal but will pass,
225 | and month and day names must be capitalized.
226 | If you want to examine the correctness look for the [\s] to denote the
227 | seperation of individual regular expressions. This is how I break them up visually
228 | to examine them:
229 |
230 | SECONDS:
231 | (
232 | ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)
233 | | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))
234 | | ([\?])
235 | | ([\*])
236 | ) [\s]
237 | MINUTES:
238 | (
239 | ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)
240 | | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))
241 | | ([\?])
242 | | ([\*])
243 | ) [\s]
244 | HOURS:
245 | (
246 | ((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?)
247 | | (([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3]))
248 | | ([\?])
249 | | ([\*])
250 | ) [\s]
251 | DAY OF MONTH:
252 | (
253 | ((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?)
254 | | (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)
255 | | (L(-[0-9])?)
256 | | (L(-[1-2][0-9])?)
257 | | (L(-[3][0-1])?)
258 | | (LW)
259 | | ([1-9]W)
260 | | ([1-3][0-9]W)
261 | | ([\?])
262 | | ([\*])
263 | )[\s]
264 | MONTH:
265 | (
266 | ((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?)
267 | | (([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2]))
268 | | (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)
269 | | ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))
270 | | ([\?])
271 | | ([\*])
272 | )[\s]
273 | DAY OF WEEK:
274 | (
275 | (([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?)
276 | | ([1-7]/([1-7]))
277 | | (((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?)
278 | | ((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)
279 | | (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?)
280 | | (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?)
281 | | ([\?])
282 | | ([\*])
283 | )
284 | YEAR (OPTIONAL):
285 | (
286 | [\s]?
287 | ([\*])?
288 | | ((19[7-9][0-9])|(20[0-9][0-9]))?
289 | | (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))?
290 | | ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)?
291 | )
292 |
293 |
294 |
295 |
297 |
298 |
299 |
300 |
301 |
302 | Number of times to repeat the Trigger (-1 for indefinite)
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 | Simple Trigger Misfire Instructions
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 | Cron Trigger Misfire Instructions
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 | Date Interval Trigger Misfire Instructions
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 | Interval Units
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzIntegration/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/ConfigurationProviderExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzService.Configuration
14 | {
15 | using System;
16 | using System.Configuration;
17 | using System.Globalization;
18 | using System.Linq;
19 | using Transports.RabbitMq.Configuration.Configurators;
20 |
21 |
22 | public static class ConfigurationProviderExtensions
23 | {
24 | public static Uri GetServiceBusUriFromSetting(this IConfigurationProvider configurationProvider,
25 | string settingName)
26 | {
27 | string queueName = configurationProvider.GetSetting(settingName);
28 | return configurationProvider.GetServiceBusUri(queueName);
29 | }
30 |
31 | public static Uri GetServiceBusUri(this IConfigurationProvider configuration, string queueName)
32 | {
33 | string scheme = configuration.GetSetting("Scheme", "rabbitmq");
34 | if (string.Compare("rabbitmq", scheme, StringComparison.OrdinalIgnoreCase) == 0)
35 | {
36 | string host = configuration.GetSetting("RabbitMQHost");
37 | string vhost = configuration.GetSetting("RabbitMQVirtualHost");
38 | string queueOptions = configuration.GetSetting("RabbitMQOptions", "");
39 |
40 | var builder = new UriBuilder("rabbitmq", host);
41 |
42 | string[] paths = vhost.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
43 |
44 | string path = string.Join("/", paths.Concat(new[]{queueName}).ToArray());
45 |
46 | builder.Path = string.Format("/{0}", string.Join("/", paths));
47 | builder.Path = path;
48 | builder.Query = queueOptions;
49 |
50 | return builder.Uri;
51 | }
52 |
53 | if (string.Compare("msmq", scheme, StringComparison.OrdinalIgnoreCase) == 0)
54 | {
55 | string host = configuration.GetSetting("MSMQHost");
56 |
57 | var builder = new UriBuilder("msmq", host);
58 |
59 | return new Uri(builder.Uri, queueName);
60 | }
61 |
62 | throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture,
63 | "An unrecognized scheme was found: {0}", scheme));
64 | }
65 |
66 |
67 | public static void ConfigureRabbitMqHost(this RabbitMqTransportFactoryConfigurator configurator,
68 | IConfigurationProvider configuration)
69 | {
70 | Uri hostAddress = GetServiceBusUri(configuration, "ignored");
71 |
72 | string userName = configuration.GetSetting("RabbitMQUsername");
73 | string password = configuration.GetSetting("RabbitMQPassword");
74 |
75 | configurator.ConfigureHost(hostAddress, h =>
76 | {
77 | h.SetUsername(userName);
78 | h.SetPassword(password);
79 | });
80 | }
81 |
82 |
83 | public static string GetSetting(this IConfigurationProvider configuration, string key, string defaultValue)
84 | {
85 | string value = configuration.GetSetting(key);
86 | if (string.IsNullOrEmpty(value))
87 | return defaultValue;
88 |
89 | return value;
90 | }
91 |
92 | public static int GetSetting(this IConfigurationProvider configuration, string key, int defaultValue)
93 | {
94 | string value = configuration.GetSetting(key);
95 | if (string.IsNullOrEmpty(value))
96 | return defaultValue;
97 |
98 | int result;
99 | if (int.TryParse(value, out result))
100 | return result;
101 |
102 | return defaultValue;
103 | }
104 |
105 | public static bool GetSetting(this IConfigurationProvider configuration, string key, bool defaultValue)
106 | {
107 | string value = configuration.GetSetting(key);
108 | if (string.IsNullOrEmpty(value))
109 | return defaultValue;
110 |
111 | bool result;
112 | if (bool.TryParse(value, out result))
113 | return result;
114 |
115 | return defaultValue;
116 | }
117 | }
118 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/ConnectionStringProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | using System.Text.RegularExpressions;
4 |
5 |
6 | public class ConnectionStringProvider :
7 | IConnectionStringProvider
8 | {
9 | IConfigurationProvider _configurationProvider;
10 |
11 | public ConnectionStringProvider(IConfigurationProvider configurationProvider)
12 | {
13 | _configurationProvider = configurationProvider;
14 | }
15 |
16 | public string GetConnectionString(string connectionName, string serverName = null, string databaseName = null)
17 | {
18 | string connectionString = _configurationProvider.GetConnectionString(connectionName);
19 | if (connectionString == null)
20 | return null;
21 |
22 | if (serverName != null)
23 | connectionString = ReplaceServerName(connectionString, serverName);
24 |
25 | if (databaseName != null)
26 | connectionString = ReplaceDatabaseName(connectionString, databaseName);
27 |
28 | return connectionString;
29 | }
30 |
31 | string ReplaceServerName(string value, string serverName)
32 | {
33 | if (serverName.IndexOfAny(new[] {'.', ':', '\\'}) >= 0)
34 | return Regex.Replace(value, @"\s*Server\s*=\s*(?[^;]+)", "Server=" + serverName,
35 | RegexOptions.IgnoreCase);
36 | return Regex.Replace(value, @"\s*Server\s*=\s*(?[^;\.:]+)", "Server=" + serverName,
37 | RegexOptions.IgnoreCase);
38 | }
39 |
40 | string ReplaceDatabaseName(string value, string databaseName)
41 | {
42 | return Regex.Replace(value, @"\s*Database\s*=\s*(?[^;]+)", "Database=" + databaseName,
43 | RegexOptions.IgnoreCase);
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/FileConfigurationProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | using System;
4 | using System.Configuration;
5 | using System.Reflection;
6 |
7 |
8 | public class FileConfigurationProvider :
9 | IConfigurationProvider
10 | {
11 | readonly Func _appSettings;
12 | readonly Func _connectionStrings;
13 | readonly Func _getSection;
14 |
15 | public FileConfigurationProvider()
16 | : this(Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly())
17 | {
18 | }
19 |
20 | public FileConfigurationProvider(Assembly assembly)
21 | {
22 | var map = new ExeConfigurationFileMap();
23 |
24 | map.ExeConfigFilename = assembly.Location + ".config";
25 |
26 | Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(map,
27 | ConfigurationUserLevel.None);
28 |
29 | _appSettings = () => configuration.AppSettings;
30 | _connectionStrings = () => configuration.ConnectionStrings;
31 | _getSection = configuration.GetSection;
32 | }
33 |
34 | public string GetSetting(string name)
35 | {
36 | AppSettingsSection settings = _appSettings();
37 | if (settings == null)
38 | return null;
39 |
40 | KeyValueConfigurationElement element = settings.Settings[name];
41 | if (element == null)
42 | return null;
43 |
44 | return element.Value;
45 | }
46 |
47 | public string GetConnectionString(string name)
48 | {
49 | ConnectionStringsSection connectionStrings = _connectionStrings();
50 | if (connectionStrings == null)
51 | return null;
52 |
53 | ConnectionStringSettings setting = connectionStrings.ConnectionStrings[name];
54 | if (setting == null)
55 | return null;
56 |
57 | return setting.ConnectionString;
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/IConfigurationProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | public interface IConfigurationProvider
4 | {
5 | string GetSetting(string name);
6 | string GetConnectionString(string name);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/IConnectionProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | using System.Data;
4 |
5 |
6 | public interface IConnectionProvider
7 | {
8 | IDbConnection GetConnection();
9 |
10 | ///
11 | /// Get a command object for executing a query against a database
12 | ///
13 | /// The SQL string
14 | /// An owned command object
15 | IDbCommand GetCommand(string sql);
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/IConnectionStringProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | ///
4 | /// A connection string source used to build out connection strings
5 | ///
6 | public interface IConnectionStringProvider
7 | {
8 | ///
9 | /// Returns the requested connection string, optionally replacing the server or catalog
10 | ///
11 | /// The name of the connection string
12 | /// Optional, the server name to use instead of the name in the setting source
13 | /// Optional, the catalog name to use instead of the name in the setting source
14 | /// A properly formatted connection string
15 | string GetConnectionString(string connectionName, string serverName = null, string databaseName = null);
16 |
17 | }
18 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Configuration/SqlConnectionProvider.cs:
--------------------------------------------------------------------------------
1 | namespace MassTransit.QuartzService.Configuration
2 | {
3 | using System.Data;
4 | using System.Data.SqlClient;
5 |
6 |
7 | public class SqlConnectionProvider :
8 | IConnectionProvider
9 | {
10 | string _connectionString;
11 |
12 | public SqlConnectionProvider(IConnectionStringProvider connectionStringProvider, string connectionName)
13 | {
14 | _connectionString = connectionStringProvider.GetConnectionString(connectionName);
15 | }
16 |
17 | public IDbConnection GetConnection()
18 | {
19 | return new SqlConnection(_connectionString);
20 | }
21 |
22 | public IDbCommand GetCommand(string sql)
23 | {
24 | var connection = new SqlConnection(_connectionString);
25 | connection.Open();
26 |
27 | var command = new SqlCommand(sql, connection);
28 |
29 | return command;
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/MassTransit.QuartzService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x86
6 | 8.0.30703
7 | 2.0
8 | {989BA511-C126-4C88-A74B-BAD83DF2291B}
9 | Exe
10 | Properties
11 | MassTransit.QuartzService
12 | MassTransit.QuartzService
13 | v4.0
14 |
15 |
16 | 512
17 | ..\
18 | true
19 |
20 |
21 | x86
22 | true
23 | full
24 | false
25 | bin\Debug\
26 | DEBUG;TRACE
27 | prompt
28 | 4
29 |
30 |
31 | x86
32 | pdbonly
33 | true
34 | bin\Release\
35 | TRACE
36 | prompt
37 | 4
38 |
39 |
40 | true
41 | bin\Debug\
42 | DEBUG;TRACE
43 | full
44 | AnyCPU
45 | bin\Debug\MassTransit.QuartzService.exe.CodeAnalysisLog.xml
46 | true
47 | GlobalSuppressions.cs
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
51 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
52 | true
53 |
54 |
55 | bin\Release\
56 | TRACE
57 | true
58 | pdbonly
59 | AnyCPU
60 | bin\Release\MassTransit.QuartzService.exe.CodeAnalysisLog.xml
61 | true
62 | GlobalSuppressions.cs
63 | prompt
64 | MinimumRecommendedRules.ruleset
65 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
66 | false
67 | ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
68 |
69 |
70 |
71 | ..\packages\Common.Logging.3.0.0\lib\net40\Common.Logging.dll
72 |
73 |
74 | ..\packages\Common.Logging.Core.3.0.0\lib\net40\Common.Logging.Core.dll
75 |
76 |
77 | False
78 | ..\packages\Common.Logging.Log4Net1211.3.0.0\lib\net40\Common.Logging.Log4Net1211.dll
79 |
80 |
81 | False
82 | ..\packages\log4net.2.0.3\lib\net40-full\log4net.dll
83 |
84 |
85 | ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll
86 | True
87 |
88 |
89 | ..\packages\MassTransit.2.10.2\lib\net40\MassTransit.dll
90 | True
91 |
92 |
93 | ..\packages\MassTransit.Log4Net.2.10.2\lib\net40\MassTransit.Log4NetIntegration.dll
94 | True
95 |
96 |
97 | ..\packages\MassTransit.MSMQ.2.10.2\lib\net40\MassTransit.Transports.MSMQ.dll
98 | True
99 |
100 |
101 | ..\packages\MassTransit.RabbitMQ.2.10.2\lib\net40\MassTransit.Transports.RabbitMq.dll
102 | True
103 |
104 |
105 | ..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll
106 | True
107 |
108 |
109 | ..\packages\Quartz.2.3.2\lib\net40\Quartz.dll
110 |
111 |
112 | ..\packages\RabbitMQ.Client.3.4.3\lib\net35\RabbitMQ.Client.dll
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | ..\packages\Topshelf.3.2.0\lib\net40-full\Topshelf.dll
121 | True
122 |
123 |
124 | ..\packages\Topshelf.Log4Net.3.2.0\lib\net40-full\Topshelf.Log4Net.dll
125 |
126 |
127 |
128 |
129 | SolutionVersion.cs
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 | Designer
145 |
146 |
147 | PreserveNewest
148 | Designer
149 |
150 |
151 |
152 |
153 |
154 | {2F7DB49B-B650-4B57-BB9D-5D1B913CCACC}
155 | MassTransit.QuartzIntegration
156 |
157 |
158 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}
159 | MassTransit.Scheduling
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
174 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzService
14 | {
15 | using System;
16 | using System.Diagnostics;
17 | using Configuration;
18 | using Log4NetIntegration.Logging;
19 | using Monitoring;
20 | using Topshelf;
21 | using Topshelf.Logging;
22 | using Topshelf.Runtime;
23 |
24 |
25 | class Program
26 | {
27 | static int Main()
28 | {
29 | Log4NetLogWriterFactory.Use("log4net.config");
30 | Log4NetLogger.Use();
31 |
32 |
33 | return (int)HostFactory.Run(x =>
34 | {
35 | x.AfterInstall(() =>
36 | {
37 | VerifyEventLogSourceExists();
38 |
39 | // this will force the performance counters to register during service installation
40 | // making them created - of course using the InstallUtil stuff completely skips
41 | // this part of the install :(
42 | ServiceBusPerformanceCounters counters = ServiceBusPerformanceCounters.Instance;
43 |
44 | string name = counters.ConsumerThreadCount.Name;
45 | Console.WriteLine("Consumer Thread Count Counter Installed: {0}", name);
46 | });
47 |
48 | x.Service(CreateService);
49 | });
50 | }
51 |
52 | static void VerifyEventLogSourceExists()
53 | {
54 | if (!EventLog.SourceExists("MassTransit"))
55 | EventLog.CreateEventSource("MassTransit Quartz Service", "MassTransit");
56 | }
57 |
58 | static ScheduleMessageService CreateService(HostSettings arg)
59 | {
60 | var configurationProvider = new FileConfigurationProvider();
61 |
62 | return new ScheduleMessageService(configurationProvider);
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/ScheduleMessageService.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.QuartzService
14 | {
15 | using System;
16 | using System.Linq;
17 | using Configuration;
18 | using Logging;
19 | using Quartz;
20 | using Quartz.Impl;
21 | using QuartzIntegration;
22 | using Topshelf;
23 |
24 |
25 | public class ScheduleMessageService :
26 | ServiceControl
27 | {
28 | readonly IConfigurationProvider _configurationProvider;
29 | readonly int _consumerLimit;
30 | readonly Uri _controlQueueUri;
31 | readonly ILog _log = Logger.Get();
32 | readonly IScheduler _scheduler;
33 | IServiceBus _bus;
34 |
35 | public ScheduleMessageService(IConfigurationProvider configurationProvider)
36 | {
37 | _configurationProvider = configurationProvider;
38 | _controlQueueUri = configurationProvider.GetServiceBusUriFromSetting("ControlQueueName");
39 | _consumerLimit = configurationProvider.GetSetting("ConsumerLimit", Math.Min(2, Environment.ProcessorCount));
40 |
41 | _scheduler = CreateScheduler();
42 | }
43 |
44 | public bool Start(HostControl hostControl)
45 | {
46 | try
47 | {
48 | _bus = ServiceBusFactory.New(x =>
49 | {
50 | // just support everything by default
51 | x.UseMsmq();
52 | x.UseRabbitMq(rmq => rmq.ConfigureRabbitMqHost(_configurationProvider));
53 | x.UseJsonSerializer();
54 |
55 | // move this to app.config
56 | x.ReceiveFrom(_controlQueueUri);
57 | x.SetConcurrentConsumerLimit(_consumerLimit);
58 |
59 | x.Subscribe(s =>
60 | {
61 | s.Consumer(() => new ScheduleMessageConsumer(_scheduler));
62 | s.Consumer(() => new CancelScheduledMessageConsumer(_scheduler));
63 |
64 | s.Consumer(() => new ScheduleTimeoutConsumer(_scheduler));
65 | s.Consumer(() => new CancelScheduledTimeoutConsumer(_scheduler));
66 | });
67 | });
68 |
69 | if (_log.IsInfoEnabled)
70 | _log.Info(GetProbeInfo());
71 |
72 | _scheduler.JobFactory = new MassTransitJobFactory(_bus);
73 |
74 | _scheduler.Start();
75 | }
76 | catch (Exception)
77 | {
78 | _scheduler.Shutdown();
79 | throw;
80 | }
81 |
82 | return true;
83 | }
84 |
85 | string GetProbeInfo()
86 | {
87 | var strings = _bus.Probe().Entries
88 | .Where(x => !x.Key.StartsWith("zz."))
89 | .Select(x => string.Format("{0}: {1}", x.Key, x.Value));
90 |
91 | var probe = string.Join(Environment.NewLine, strings.ToArray());
92 | return probe;
93 | }
94 |
95 | public bool Stop(HostControl hostControl)
96 | {
97 | _scheduler.Standby();
98 |
99 | if (_bus != null)
100 | _bus.Dispose();
101 |
102 | _scheduler.Shutdown();
103 |
104 | return true;
105 | }
106 |
107 | static IScheduler CreateScheduler()
108 | {
109 | ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
110 |
111 | IScheduler scheduler = schedulerFactory.GetScheduler();
112 |
113 | return scheduler;
114 | }
115 | }
116 | }
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/job_scheduling_data_2_0.xsd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 | Root level node
12 |
13 |
14 |
15 |
16 |
17 | Commands to be executed before scheduling the jobs and triggers in this file.
18 |
19 |
20 |
21 |
22 | Directives to be followed while scheduling the jobs and triggers in this file.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Version of the XML Schema instance
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | Delete all jobs, if any, in the identified group. "*" can be used to identify all groups. Will also result in deleting all triggers related to the jobs.
47 |
48 |
49 |
50 |
51 | Delete all triggers, if any, in the identified group. "*" can be used to identify all groups. Will also result in deletion of related jobs that are non-durable.
52 |
53 |
54 |
55 |
56 | Delete the identified job if it exists (will also result in deleting all triggers related to it).
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | Delete the identified trigger if it exists (will also result in deletion of related jobs that are non-durable).
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | Whether the existing scheduling data (with same identifiers) will be overwritten. If false, and ignore-duplicates is not false, and jobs or triggers with the same names already exist as those in the file, an error will occur.
84 |
85 |
86 |
87 |
88 | If true (and overwrite-existing-data is false) then any job/triggers encountered in this file that have names that already exist in the scheduler will be ignored, and no error will be produced.
89 |
90 |
91 |
92 |
93 | If true trigger's start time is calculated based on earlier run time instead of fixed value. Trigger's start time must be undefined for this to work.
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Define a JobDetail
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | Define a JobDataMap
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | Define a JobDataMap entry
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | Define a Trigger
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 | Common Trigger definitions
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | Define a SimpleTrigger
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | Define a CronTrigger
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 | Define a DateIntervalTrigger
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 | Cron expression (see JavaDoc for examples)
220 |
221 | Special thanks to Chris Thatcher (thatcher@butterfly.net) for the regular expression!
222 |
223 | Regular expressions are not my strong point but I believe this is complete,
224 | with the caveat that order for expressions like 3-0 is not legal but will pass,
225 | and month and day names must be capitalized.
226 | If you want to examine the correctness look for the [\s] to denote the
227 | seperation of individual regular expressions. This is how I break them up visually
228 | to examine them:
229 |
230 | SECONDS:
231 | (
232 | ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)
233 | | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))
234 | | ([\?])
235 | | ([\*])
236 | ) [\s]
237 | MINUTES:
238 | (
239 | ((([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?,)*([0-9]|[0-5][0-9])(-([0-9]|[0-5][0-9]))?)
240 | | (([\*]|[0-9]|[0-5][0-9])/([0-9]|[0-5][0-9]))
241 | | ([\?])
242 | | ([\*])
243 | ) [\s]
244 | HOURS:
245 | (
246 | ((([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?,)*([0-9]|[0-1][0-9]|[2][0-3])(-([0-9]|[0-1][0-9]|[2][0-3]))?)
247 | | (([\*]|[0-9]|[0-1][0-9]|[2][0-3])/([0-9]|[0-1][0-9]|[2][0-3]))
248 | | ([\?])
249 | | ([\*])
250 | ) [\s]
251 | DAY OF MONTH:
252 | (
253 | ((([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?,)*([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(-([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1]))?(C)?)
254 | | (([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])/([1-9]|[0][1-9]|[1-2][0-9]|[3][0-1])(C)?)
255 | | (L(-[0-9])?)
256 | | (L(-[1-2][0-9])?)
257 | | (L(-[3][0-1])?)
258 | | (LW)
259 | | ([1-9]W)
260 | | ([1-3][0-9]W)
261 | | ([\?])
262 | | ([\*])
263 | )[\s]
264 | MONTH:
265 | (
266 | ((([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?,)*([1-9]|0[1-9]|1[0-2])(-([1-9]|0[1-9]|1[0-2]))?)
267 | | (([1-9]|0[1-9]|1[0-2])/([1-9]|0[1-9]|1[0-2]))
268 | | (((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?,)*(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)(-(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))?)
269 | | ((JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))
270 | | ([\?])
271 | | ([\*])
272 | )[\s]
273 | DAY OF WEEK:
274 | (
275 | (([1-7](-([1-7]))?,)*([1-7])(-([1-7]))?)
276 | | ([1-7]/([1-7]))
277 | | (((MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?,)*(MON|TUE|WED|THU|FRI|SAT|SUN)(-(MON|TUE|WED|THU|FRI|SAT|SUN))?(C)?)
278 | | ((MON|TUE|WED|THU|FRI|SAT|SUN)/(MON|TUE|WED|THU|FRI|SAT|SUN)(C)?)
279 | | (([1-7]|(MON|TUE|WED|THU|FRI|SAT|SUN))(L|LW)?)
280 | | (([1-7]|MON|TUE|WED|THU|FRI|SAT|SUN)#([1-7])?)
281 | | ([\?])
282 | | ([\*])
283 | )
284 | YEAR (OPTIONAL):
285 | (
286 | [\s]?
287 | ([\*])?
288 | | ((19[7-9][0-9])|(20[0-9][0-9]))?
289 | | (((19[7-9][0-9])|(20[0-9][0-9]))/((19[7-9][0-9])|(20[0-9][0-9])))?
290 | | ((((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?,)*((19[7-9][0-9])|(20[0-9][0-9]))(-((19[7-9][0-9])|(20[0-9][0-9])))?)?
291 | )
292 |
293 |
294 |
295 |
297 |
298 |
299 |
300 |
301 |
302 | Number of times to repeat the Trigger (-1 for indefinite)
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 | Simple Trigger Misfire Instructions
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 | Cron Trigger Misfire Instructions
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 | Date Interval Trigger Misfire Instructions
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 | Interval Units
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/log4net.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/src/MassTransit.QuartzService/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/CancelScheduledMessage.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.Scheduling
14 | {
15 | using System;
16 |
17 |
18 | public interface CancelScheduledMessage :
19 | CorrelatedBy
20 | {
21 | ///
22 | /// The date/time this message was created
23 | ///
24 | DateTime Timestamp { get; }
25 |
26 | ///
27 | /// The token of the scheduled message
28 | ///
29 | Guid TokenId { get; }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/MassTransit.Scheduling.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | 8.0.30703
7 | 2.0
8 | {863EBFC8-DFA6-45E7-B9ED-4D180FE2BE00}
9 | Library
10 | Properties
11 | MassTransit.Scheduling
12 | MassTransit.Scheduling
13 | v4.0
14 | 512
15 | ..\
16 | true
17 |
18 |
19 |
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 | ..\packages\Magnum.2.1.3\lib\NET40\Magnum.dll
39 | True
40 |
41 |
42 | ..\packages\MassTransit.2.10.2\lib\net40\MassTransit.dll
43 | True
44 |
45 |
46 | ..\packages\Newtonsoft.Json.6.0.6\lib\net40\Newtonsoft.Json.dll
47 | True
48 |
49 |
50 |
51 |
52 |
53 |
54 | SolutionVersion.cs
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
76 |
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/ScheduleMessage.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.Scheduling
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 |
18 |
19 | public interface ScheduleMessage :
20 | CorrelatedBy
21 | {
22 | ///
23 | /// The time at which the message should be published
24 | ///
25 | DateTime ScheduledTime { get; }
26 |
27 | ///
28 | /// The message types implemented by the message
29 | ///
30 | IList PayloadType { get; }
31 |
32 | ///
33 | /// The destination where the message should be sent
34 | ///
35 | Uri Destination { get; }
36 | }
37 |
38 |
39 | public interface ScheduleMessage :
40 | ScheduleMessage
41 | where T : class
42 | {
43 | ///
44 | /// The message to be published
45 | ///
46 | T Payload { get; }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/ScheduleMessageExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.Scheduling
14 | {
15 | using System;
16 | using System.Collections.Generic;
17 | using System.Linq;
18 |
19 |
20 | ///
21 | /// Extensions for scheduling publish/send message
22 | ///
23 | public static class ScheduleMessageExtensions
24 | {
25 | ///
26 | /// Sends a ScheduleMessage command to the endpoint, using the specified arguments
27 | ///
28 | /// The scheduled message type
29 | /// The endpoint of the message scheduling service
30 | /// The destination address where the schedule message should be sent
31 | /// The time when the message should be sent to the endpoint
32 | /// The message to send
33 | /// A handled to the scheduled message
34 | public static ScheduledMessage ScheduleSend(this IEndpoint endpoint, Uri destinationAddress, DateTime scheduledTime, T message)
35 | where T : class
36 | {
37 | var command = new ScheduleMessageCommand(scheduledTime, destinationAddress, message);
38 |
39 | endpoint.Send>(command);
40 |
41 | return new ScheduledMessageHandle(command.CorrelationId, command.ScheduledTime, command.Destination,
42 | command.Payload);
43 | }
44 |
45 | ///
46 | /// Sends a ScheduleMessage command to the endpoint, using the specified arguments
47 | ///
48 | /// The scheduled message type
49 | /// The endpoint of the message scheduling service
50 | /// The destionation address for the schedule message
51 | /// The time when the message should be sent to the endpoint
52 | /// The message to send
53 | ///
54 | public static ScheduledMessage ScheduleSend(this IEndpoint endpoint, IEndpointAddress destinationAddress, DateTime scheduledTime, T message)
55 | where T : class
56 | {
57 | return ScheduleSend(endpoint, destinationAddress.Uri, scheduledTime, message);
58 | }
59 |
60 | ///
61 | /// Sends a ScheduleMessage command to the endpoint, using the specified arguments
62 | ///
63 | /// The scheduled message type
64 | /// The endpoint of the message scheduling service
65 | /// The bus instance where the scheduled message should be sent
66 | /// The time when the message should be sent to the endpoint
67 | /// The message to send
68 | ///
69 | public static ScheduledMessage ScheduleSend(this IEndpoint endpoint, IServiceBus bus, DateTime scheduledTime, T message)
70 | where T : class
71 | {
72 | return ScheduleSend(endpoint, bus.Endpoint.Address.Uri, scheduledTime, message);
73 | }
74 |
75 | ///
76 | /// Sends a ScheduleMessage command to the endpoint, using the specified arguments
77 | ///
78 | /// The scheduled message type
79 | /// The endpoint of the message scheduling service
80 | /// The destination endpoint where the scheduled message should be sent
81 | /// The time when the message should be sent to the endpoint
82 | /// The message to send
83 | ///
84 | public static ScheduledMessage ScheduleSend(this IEndpoint endpoint, IEndpoint destinationEndpoint, DateTime scheduledTime, T message)
85 | where T : class
86 | {
87 | return ScheduleSend(endpoint, destinationEndpoint.Address.Uri, scheduledTime, message);
88 | }
89 |
90 | ///
91 | /// Cancel a scheduled message using the scheduled message instance
92 | ///
93 | /// The endpoint of the scheduling service
94 | /// The schedule message reference
95 | public static void CancelScheduledSend(this IEndpoint endpoint, ScheduledMessage message)
96 | where T : class
97 | {
98 | if (message == null)
99 | throw new ArgumentNullException("message");
100 |
101 | CancelScheduledSend(endpoint, message.TokenId);
102 | }
103 |
104 | ///
105 | /// Cancel a scheduled message using the tokenId that was returned when the message was scheduled.
106 | ///
107 | /// The endpoint of the scheduling service
108 | /// The tokenId of the scheduled message
109 | public static void CancelScheduledSend(this IEndpoint endpoint, Guid tokenId)
110 | {
111 | var command = new CancelScheduledMessageCommand(tokenId);
112 |
113 | endpoint.Send(command);
114 | }
115 |
116 |
117 | ///
118 | /// Schedules a message to be sent to the bus using a Publish, which should only be used when
119 | /// the quartz service is on a single shared queue or behind a distributor
120 | ///
121 | /// The scheduled message type
122 | /// The bus from which the scheduled message command should be published
123 | /// The destination address where the schedule message should be sent
124 | /// The time when the message should be sent to the endpoint
125 | /// The message to send
126 | /// Optional: A callback that gives the caller access to the publish context.
127 | /// A handled to the scheduled message
128 | public static ScheduledMessage ScheduleMessage(this IServiceBus bus, Uri destinationAddress, DateTime scheduledTime, T message, Action>> contextCallback = null)
129 | where T : class
130 | {
131 | var command = new ScheduleMessageCommand(scheduledTime, destinationAddress, message);
132 |
133 | bus.Publish>(command, contextCallback ?? (c => {}));
134 |
135 | return new ScheduledMessageHandle(command.CorrelationId, command.ScheduledTime, command.Destination,
136 | command.Payload);
137 | }
138 |
139 | ///
140 | /// Schedules a message to be sent to the bus using a Publish, which should only be used when
141 | /// the quartz service is on a single shared queue or behind a distributor
142 | ///
143 | /// The scheduled message type
144 | /// The bus from which the scheduled message command should be published
145 | /// The destination address where the schedule message should be sent
146 | /// The time when the message should be sent to the endpoint
147 | /// The message to send
148 | /// A handled to the scheduled message
149 | public static ScheduledMessage ScheduleMessage(this IServiceBus bus, IEndpointAddress destinationAddress, DateTime scheduledTime, T message)
150 | where T : class
151 | {
152 | return ScheduleMessage(bus, destinationAddress.Uri, scheduledTime, message);
153 | }
154 |
155 | ///
156 | /// Schedules a message to be sent to the bus using a Publish, which should only be used when
157 | /// the quartz service is on a single shared queue or behind a distributor
158 | ///
159 | /// The scheduled message type
160 | /// The bus from which the scheduled message command should be published
161 | /// The destination address where the schedule message should be sent
162 | /// The time when the message should be sent to the endpoint
163 | /// The message to send
164 | /// A handled to the scheduled message
165 | public static ScheduledMessage ScheduleMessage(this IServiceBus bus, IEndpoint destinationEndpoint, DateTime scheduledTime, T message)
166 | where T : class
167 | {
168 | return ScheduleMessage(bus, destinationEndpoint.Address.Uri, scheduledTime, message);
169 | }
170 |
171 | ///
172 | /// Schedules a message to be sent to the bus using a Publish, which should only be used when
173 | /// the quartz service is on a single shared queue or behind a distributor
174 | ///
175 | /// The scheduled message type
176 | /// The bus from which the scheduled message command should be published
177 | /// The time when the message should be sent to the endpoint
178 | /// The message to send
179 | /// /// Optional: A callback that gives the caller access to the publish context.
180 | /// A handled to the scheduled message
181 | public static ScheduledMessage ScheduleMessage(this IServiceBus bus, DateTime scheduledTime, T message, Action>> contextCallback = null)
182 | where T : class
183 | {
184 | return ScheduleMessage(bus, bus.Endpoint.Address.Uri, scheduledTime, message, contextCallback);
185 | }
186 |
187 | ///
188 | /// Cancel a scheduled message using the scheduled message instance
189 | ///
190 | ///
191 | ///
192 | public static void CancelScheduledMessage(this IServiceBus bus, ScheduledMessage message)
193 | where T : class
194 | {
195 | if (message == null)
196 | throw new ArgumentNullException("message");
197 |
198 | CancelScheduledMessage(bus, message.TokenId);
199 | }
200 |
201 | ///
202 | /// Cancel a scheduled message using the tokenId that was returned when the message was scheduled.
203 | ///
204 | ///
205 | /// The tokenId of the scheduled message
206 | public static void CancelScheduledMessage(this IServiceBus bus, Guid tokenId)
207 | {
208 | var command = new CancelScheduledMessageCommand(tokenId);
209 |
210 | bus.Publish(command);
211 | }
212 |
213 |
214 | class CancelScheduledMessageCommand :
215 | CancelScheduledMessage
216 | {
217 | public CancelScheduledMessageCommand(Guid tokenId)
218 | {
219 | CorrelationId = NewId.NextGuid();
220 | Timestamp = DateTime.UtcNow;
221 |
222 | TokenId = tokenId;
223 | }
224 |
225 | public Guid TokenId { get; private set; }
226 | public DateTime Timestamp { get; private set; }
227 | public Guid CorrelationId { get; private set; }
228 | }
229 |
230 |
231 | class ScheduleMessageCommand :
232 | ScheduleMessage
233 | where T : class
234 | {
235 | public ScheduleMessageCommand(DateTime scheduledTime, Uri destination, T payload)
236 | {
237 | CorrelationId = NewId.NextGuid();
238 |
239 | ScheduledTime = scheduledTime.Kind == DateTimeKind.Local
240 | ? scheduledTime.ToUniversalTime()
241 | : scheduledTime;
242 |
243 | Destination = destination;
244 | Payload = payload;
245 |
246 | PayloadType = typeof(T).GetMessageTypes()
247 | .Select(x => new MessageUrn(x).ToString())
248 | .ToList();
249 | }
250 |
251 | public Guid CorrelationId { get; private set; }
252 | public DateTime ScheduledTime { get; private set; }
253 | public IList PayloadType { get; private set; }
254 | public Uri Destination { get; private set; }
255 | public T Payload { get; private set; }
256 | }
257 |
258 |
259 | class ScheduledMessageHandle :
260 | ScheduledMessage
261 | where T : class
262 | {
263 | public ScheduledMessageHandle(Guid tokenId, DateTime scheduledTime, Uri destination, T payload)
264 | {
265 | TokenId = tokenId;
266 | ScheduledTime = scheduledTime;
267 | Destination = destination;
268 | Payload = payload;
269 | }
270 |
271 | public Guid TokenId { get; private set; }
272 | public DateTime ScheduledTime { get; private set; }
273 | public Uri Destination { get; private set; }
274 | public T Payload { get; private set; }
275 | }
276 | }
277 | }
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/ScheduledMessage.cs:
--------------------------------------------------------------------------------
1 | // Copyright 2007-2012 Chris Patterson, Dru Sellers, Travis Smith, et. al.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4 | // this file except in compliance with the License. You may obtain a copy of the
5 | // License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software distributed
10 | // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | // specific language governing permissions and limitations under the License.
13 | namespace MassTransit.Scheduling
14 | {
15 | using System;
16 |
17 |
18 | public interface ScheduledMessage
19 | where T : class
20 | {
21 | Guid TokenId { get; }
22 | DateTime ScheduledTime { get; }
23 | Uri Destination { get; }
24 | T Payload { get; }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/MassTransit.Scheduling/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/packages/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------