GithubHelp home page GithubHelp logo

jamesmh / coravel Goto Github PK

View Code? Open in Web Editor NEW
3.6K 62.0 241.0 3.11 MB

Near-zero config .NET library that makes advanced application features like Task Scheduling, Caching, Queuing, Event Broadcasting, and more a breeze!

Home Page: https://docs.coravel.net/Installation/

License: MIT License

C# 94.02% CSS 0.22% JavaScript 0.41% HTML 5.21% Stylus 0.13%
dotnetcore background-jobs queue mailing hacktoberfest dotnet scheduled-jobs dotnet-core background-thread background-worker

coravel's Introduction

Netlify Status

Nuget NuGet

Coravel

Coravel helps developers get their .NET applications up and running fast by making advanced application features like task/job scheduling, queuing, caching, mailing (and more!) accessible and easy to use. Comes with simple, expressive and straightforward syntax.

You can view the official docs here.

Coravel Scheduler

Features:

Task/Job Scheduling

Usually, you have to configure a cron job or a task via Windows Task Scheduler to get a single or multiple re-occurring tasks to run.

With Coravel, you can setup all your scheduled tasks in one place using a simple, elegant, fluent syntax - in code!

Queuing

Coravel gives you a zero-configuration queue that runs in-memory to offload long-winded tasks to the background instead of making your users wait for their HTTP request to finish!

Caching

Coravel provides you with an easy to use API for caching in your .NET Core applications.

By default, it uses an in-memory cache, but also has database drivers for more robust scenarios!

Event Broadcasting

Coravel's event broadcasting helps you to build maintainable applications who's parts are loosely coupled!

Mailing

E-mails are not as easy as they should be. Luckily for you, Coravel solves this by offering:

  • Built-in e-mail friendly razor templates
  • Simple and flexible mailing API
  • Render your e-mails for visual testing
  • Drivers supporting SMTP, local log file or BYOM ("bring your own mailer") driver
  • Quick and simple configuration via appsettings.json
  • And more!

Samples

Support Me

You can support my ongoing open-source work on BuyMeACoffee.

Coravel Pro

If you are building a .NET application with Entity Framework then you might want to look into Coravel Pro. It is an admin panel & tools to make maintaining and managing your .NET app a breeze!

  • Visual job scheduling & management
  • Scaffold a CRUD UI for managing your EF entities
  • Easily configure a dashboard to show health metrics (or whatever you want)
  • Build custom tabular reports of your data
  • And more!

FAQ

How is Coravel different from Hangfire?

Hangfire has been around for a while - before modern .NET (Core). It's a fantastic tool that has tons of features that Coravel doesn't. Notably: persistent queues, retry mechanisms, support for many storage drivers, etc.

However, Hangfire still (as of March 2023) does not natively support true async/await (here and here). This means that using Hangfire within a web application, for example, won't be as efficient as it could be when using threads that perform I/O operations.

Coravel was created with modern C# and .NET primitives in mind - such as async/await and .NET's built-in dependency injection utilities. This means that Coravel can be easier to configure and will be very efficient with / won't hog threads that your web application needs to respond to incoming HTTP requests.

How is Coravel different from Quartz?

Quartz is an older Java library ported to .NET. It still doesn't hook into the modern .NET dependency injection tooling well. Some think that Coravel's APIs are much more succinct and understandable.

For example, compare this sample from their documentation with how working with Coravel is (e.g. you don't need to understand how to "start" and "stop" Coravel's scheduler, but you do have to manually work with the Quartz scheduler).

Does Coravel support persisting queued jobs to storage in case my application goes down?

No. At least, not yet.

Coravel processes queued items in-memory. When your application goes down it won't allow the application to shutdown until all items are processed.

Does Coravel support retry mechanisms?

Coravel's philosophy has been to work well with other .NET primitives - which means that using other libraries is easy.

Coravel doesn't support retry mechanisms internally because I am very careful not to bloat Coravel with things that aren't necessary. I want to keep Coravel focused on what it does best (e.g. "I need job scheduling, queuing, etc. without requiring extra infrastructure and complicated configuration").

For example, you can use Polly within your invocables to do retries. Some people will configure a base class that inherits from IInvocable that has retries built-in.

Does Coravel support distributed locking?

No. However, this can again be achieved by using a battle-tested distributed locking library like DistributedLock. You might create an invocable's Invoke() like this:

public class TestInvocable : IInvocable
{
  private ApplicationDbContext _context;
  private IDistributedLockProvider _distributedlock;

  public TestInvocable(ApplicationDbContext context, IDistributedLockProvider distributedlock)
  {
    this._context = context;
    this._distributedlock = distributedlock;
  }

  public async Task Invoke()
  {
    await using (await this._distributedlock.AcquireAsync())
    {
      await this._context.Test.AddAsync(new TestModel() { Name = "test name" });
      await this._context.SaveChangesAsync();
    }
  }
}

coravel's People

Contributors

alandecastros avatar arunpratap26 avatar blinke avatar cemsagan avatar codyschrank avatar daniel15 avatar danrovito avatar dependabot[bot] avatar dominikherold avatar dreamescaper avatar emremp avatar evan-buss avatar ezergil avatar felpel avatar jamesmh avatar jhmckimm avatar karthikveeraj avatar mattwelke avatar midyro avatar mustakimali avatar p-de-jong avatar papakaliati avatar rajmondburgaj avatar riex406 avatar seymourpoler avatar temesinko avatar tolbxela avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coravel's Issues

Queue Size?

I would like to set the max queue size, and I would maybe also like to see how long an item has been queued for. Is this possible?

.DailyAt(19, 56); does not seem to be working?

Hi,

I'm on Mac with asp.net core 2.1.

When I schedule a task like this:

services.AddScheduler(scheduler =>
            {
                scheduler.Schedule(() =>
                {
                    var job = sp.GetService<SendEmailDigestJob>();
                    job.Execute();
                })
                         .DailyAt(19, 56);
            });

Nothing ever seems to get fired.

When I schedule it like this:

services.AddScheduler(scheduler =>
            {
                scheduler.Schedule(() =>
                {
                    var job = sp.GetService<SendEmailDigestJob>();
                    job.Execute();
                })
                         .EveryMinute();
            });

Everything works as expected.

Any ideas?

Coravel looks great! Keep it up!

Queuing feature not working?

I'm playing around queuing functionality a little bit, but no luck...
Steps:

  1. Cloned Coravel repository
  2. Add a Test console project, which reffers Coravel project
  3. The code from Test console:
class Program
	{
		static void Main(string[] args)
		{
			var serviceProvider = new ServiceCollection()
				.AddQueue()
				.BuildServiceProvider();
			var queue = serviceProvider.GetRequiredService<IQueue>();
			queue.QueueTask(() =>
			{
				Console.WriteLine("This was queued!");//not firing
			});

			queue.QueueAsyncTask(async () => {
				await Task.Delay(1000);
				Console.WriteLine("This was queued async!");//not firing
			});

			serviceProvider
				.ConfigureQueue()
				.OnError(e =>
				{
					Console.WriteLine(e.Message);//not firing
				});
			Console.ReadKey();
		}
	}

The queued tasks not firing. I put a breakpoint in QueuingHost:StartAsync method, where queuing timer seems to be started, but not firing. Did I miss something?

UseCoravelPro() error

Describe the bug
I have an error at this line: app.UseCoravelPro(). The error says:

System.InvalidOperationException: 'No service for type 'GP.SS.Database.SaldeoSynchronizatorContext' has been registered.'

But according to the documentation I have registered it:

services.AddDbContext<ISaldeoSynchronizatorContext, SaldeoSynchronizatorContext>( opts => opts.UseOracle(Configuration.GetConnectionString("SaldeoSynchronizatorDB"), b => b.MigrationsAssembly(typeof(ISaldeoSynchronizatorContext).Namespace)) );

services.AddCoravelPro(typeof(SaldeoSynchronizatorContext));

Affected Coravel Feature
Using CoravelPro

Expected behaviour
To be working :)

EDIT: I moved it to the CoravelPro topic -> jamesmh/coravelpro#8

Allow sub-minute scheduling

Would you consider supporting sub-minute task scheduling? Perhaps down to the second.

I'm writing a status checking application that polls other applications to make sure they are reachable. We are using an asp net core application with an IHostedService that uses a timer to poll every X seconds. We would like to switch to using Coravel, but are concerned about limiting how often we can poll to once a minute.

Thank you.

Queue time

Hi,

First of all, thanks for the great work. ๐Ÿ‘
But i was just wondering if there are any plans to make the 30 second queue time configurable.
Right now, debugging is a pain when you have to wait 30 seconds :)

Is it possible to queue an invocable with arguments?

Thanks for this really useful, and simple to use library!

I'd like to be able to queue an invocable that accepts a parameter which is then available in its Invoke method.

e.g. something like this

Queue the invocable:

_queue.QueueInvocable<SalesOrderProcessor>(salesOrderId);

Invocable implementation:

public class SalesOrderProcessor : IInvocable
{
    public Task Invoke(int salesOrderId)
    {
        // load sales order e.g.
        //   var salesOrder = await _context.SalesOrders.FindAsync(salesOrderId);

        // process sales order
    }
}

I can't see that this is possible at the moment, or have I missed something?

Cancellation support for queued Invokables

Do you have anything like this in the pipeline?

Say one wants to build an API responsible for managing long-running background tasks. A POST might create a job with some associated metadata and a unique identifier, store that somewhere (say, in memory or in a DB), then queue up the job and return the identifier to the client. A GET looks up and returns metadata by key. A DELETE cancels a job if it's still running.

I've considered FluentScheduler, but it doesn't appear to have cancellation support either, and it also doesn't come with queueing or IHostedService baked in. Hangfire has cancellation support along with built-in persistence and a nice dashboard, but I don't like the fact that its async support is just nominal; it blocks waiting on tasks to complete. My jobs are long and heavily IO-bound, and I can't really afford for each one to sit on a thread for 3 hours. It seems real async support is planned, but it's not clear when we might see it.

For now I'm just writing my own background service. But if you do end up adding a feature like this, I'd love to take advantage of it and delete a bunch of custom code :)

In any case, thanks for your work. This is a really useful project.

Scheduler PreventOverlapping what happens with Overlapping Tasks

Hello, sorry for using your Issue Tracker for a simple Question,
but actually hwhat is happening when using PreventOverlapping on a Scheduler?

Does it:

  • Skip the Task (preferred for my work)
  • Enqueue it so that it will run after the previous task ended?

(Maybe it should be reflected in the Documentation, because if you have a scheduled task that calls http services and it's running into a timeout it will hog more and more resource, without any reason)

DisposedExecption occurs injecting

I have an IInvocable that uses aspnetcore DI to inject a normal DbContext into the constructor:

    public class MigrationCreateTask : Coravel.Invocable.IInvocable
    {
        private readonly SecurityPortalDbContext _context;
       
        public MigrationCreateTask(SecurityPortalDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }

When I use it later in the Invoke

            var localClients = _context.Modules.AsNoTracking();

I end up with an ObjectDisposedException against the dbContext. This is correct as the DBContext only exists for the scope of the initial controller request that queued the task.
Therefore I don't think this is specifically a Coravel issue. Would it be possible to create a sample explaining the "recommended" approach for such a workflow.

Build IQueuedJob

This contract will allow queuing objects instead of methods / actions.

Will allow object serialization also, a needed step for persistance, failure re-try, etc.

IQueuedJob job = new SomeQueuedItem(user); // Inject user object to be used in job....
queue.QueueJob(job);

Question: Is there any way to run an invocable on demand while respecting PreventOverlapping?

So lets say we have a moderately heavy job that imports something to our db every 20 minutes. Occasionally we are asked to run this manually because the 20 minutes wait is just to long, using Coravel we could then trigger this using the Queue, but if we're unlucky this would coincide with the scheduled run every twenty minutes, which would cause some issues in legacy exports we have. Can this overlap be detected and avoided?

As an alternative it would be nice if we could schedule a one off run of an invocable, like scheduler.Schedule().Once();
That way it could take the overlappingprotection into account and share the same thread as the regular execution.

Use EverySecond() on Configure() method wrong

I used program as follow on startup.cs ->Configure() method,

              provider.UseScheduler(scheduler =>
                  {
                      scheduler.Schedule(() => Console.WriteLine("Every minute during the week."))
                      .EverySecond()
                      .Weekday();
                  });

but dispaly "System.NullReferenceException:โ€œObject reference not set to an instance of an object.โ€" on System.Private.CoreLib.dll

But when I use program as follow on startup.cs ->Configure() method,

              provider.UseScheduler(scheduler =>
                  {
                      scheduler.Schedule(() => Console.WriteLine("Every minute during the week."))
                      .EveryMinute()
                      .Weekday();
                  });

It is normal.

Why .EveryMinute() method is normal? And EverySecond() method is wrong

Add ScheduleInvocableType to interface

Describe the solution you'd like
The ability to add a scheduled IInvocable through a type instead of through generic, action, or func. There already seems to be a method for this named IScheduleInterval ScheduleInvocableType(Type invocableType) but it is not a requirement from the interface of IScheduler.

Describe alternatives you've considered
You could work around and schedule a list of types like below but it would not work nicely with dependency injection since nothing would actually be injected from the service provider.

foreach(var type in types)
{
    schedule.Schedule(() =>
    {
        (Activator.CreateInstance(type) as IInvocable).Invoke();
    }).Cron("*/5 * * * *");
}

I did fork and make the changes here. From the looks of it no tests or anything would really need to be added since the tests are already using the method in question. This just allows it to be used with the IScheduler. Though if I am missing something that already does this it would be great to know!

How it would appear
If the other one was available through the interface we could do -

foreach(var type in types)
{
    schedule.ScheduleInvocableType(type).Cron("*/5 * * * *");
}

Make IScheduler Available Via Service Container

Right now you can't schedule tasks outside of the Startup.cs

We can configure DI to use the IScheduler interface to expose the scheduler to controller etc.

Also, internally to the hosted service.... - it's static right now :(

support netstandard2

thanks for this wonderful library
would you please add support for .Net Standard 2.0
as it is used exclusively in the infrastructure layer and business layer
and .net core only used in web layer

Invocable lifetime

I would like to call a method in my invocable from a hosted service but it's only possible if i register invocable in transient lifetime.
In docs invocable is registered:
services.AddScoped<SendNightlyReportsEmailJob>();

Will something brake in Coravel internally if i register my invocable as transient? For example:
services.AddTransient<SendNightlyReportsEmailJob>();

Scheduler not working with invocable

Hei, just starting up looking into how to use coravel in my project. Im finding that even when i follow the documentation coravel never executes schedule task when they are invocables.
What works:

app.ApplicationServices.UseScheduler(scheduler =>
{
    scheduler.Schedule(() => Console.WriteLine("Scheduled task.")).EveryMinute();
});

What doesnt work:

app.ApplicationServices.UseScheduler(scheduler =>
{
    scheduler.Schedule<SendDailyStatsReport>().EveryMinute();
});
....
using System;
using System.Threading.Tasks;
using Coravel.Invocable;

namespace bot.Invocables
{
    public class SendDailyStatsReport : IInvocable
    {
        public async Task Invoke()
        {
            Console.WriteLine("Doing expensive calculation for 15 sec...");
            await Task.Delay(15000);
            Console.WriteLine("Expensive calculation done.");
        }
    }
}

If i debug the code and set breakpoint inside Invoke method then it is never hit.
Using latest nuget packet for coravel.

Invokable Method Naming

This is more like a formal "problem".

Maybe the Invoke method of IInvocable should be renamed to InvokeAsync?

For example IListener already contains the method HandleAsync with the right suffix for an async method returning a Task.

What do you think? Renaming the method would certainly be a breaking change for the API.

System.Reflection.TargetException In Queuing Events

Describe the bug
I am trying to queue an event with the following line

_queue.QueueBroadcast(new PurchaseCreatedEvent(organisation, purchase));

When the event is broadcasted the following exception is raised

System.Reflection.TargetException
Message : Non-static method requires a target.
StackTrace :    at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Coravel.Events.Dispatcher.Broadcast[TEvent](TEvent toBroadcast)
   at Coravel.Queuing.Queue.<>c__DisplayClass10_0`1.<<QueueBroadcast>b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Coravel.Tasks.ActionOrAsyncFunc.Invoke()
   at Coravel.Queuing.Queue.InvokeTask(ActionOrAsyncFunc task)
Help Link : 
Source : System.Private.CoreLib

Affected Coravel Feature
The Coravel Feature is Queuing

Expected behaviour
I am expecting that when the queue starts the listeners of the broadcasted event handle the event. I am using Coravel with ASP NET Core 2.1.4

one .sln with all files

Hello James,
First of all thank you for all your kind contributions.
I think that It may be itneresting add a solution file (.sln) with all files. For example: Covarel.All.Visual.Studio.2017.sln, because the current version of Visual Studio is 2017.
A posible solution:

covarelsolution

Thank you. James

Build IScheduledJob

Will allow scheduling objects instead of functions.

First step in persistance.

IScheduledJob = new SomeJob();
scheduler.Schedule(job);

Adding new task to scheduler from another service

I would like to add tasks to scheduler dynamically in a service what gets the execution times from configuration file. At the moment its done in the application Configure method and every time configuration is changed i would have to restart the whole program. Is this something what could be possible with current scheduler implementation?

Scheduler is not working

I tried making a scheduler in .NET Core 2.1 running on Windows Server 2016 with IIS, but unfortunately doesn't work. Here is the code:

services.AddScheduler(scheduler =>
            {
                scheduler.Schedule(
                    () =>
                    {
                        // Makes API Call
                    }
                )
                .EveryMinute();
            }

Expected: Works and calls API

Actual: Doesn't do anything

When() Fluent Restriction

User's should have an additional method available when adding restrictions to their scheduled events.

The syntax would look like this:

scheduler.Schedule(() => //.... do the stufff )
    .EveryMinute()
    .Monday()
    .When(() => someValue = false);

The scheduled event will not fire if When returns false.

Internally this should be a collection of Func<Bool> , in the event that the user wants to call When multiple times with different conditions etc.

For now, this issue will be pending the next release as it contains an overhaul to the scheduling internals.

Long-running Queued Task Killed On App Close

When a queued task has not been invoked yet and the app is sent the kill signal, the queue does the right thing in the background.

But, if the queue has already started to consume tasks - and they are longer running tasks - they will be killed when the app's kill signal is sent.

Coravel needs to detect that previous queue iterations might have had long running tasks that are still running at app close.

Separate packages?

Hi, I have been looking for task scheduler to run in asp.net core and this looks great. I am hesitant to install the nuget however due to dependencies I do not require.

Would you consider splitting Caching/Mail/Queuing/Scheduling into independent packages so that users can pick and chose their dependencies?

I wouldn't have minded installing the components I have no use for (Caching/Mail/Queuing), however the dependency on Mailkit is a show stopper for me.

ICache Missing Has and Get

A common pattern for caches are getting values without setting them and also checking if a key exists.

Similar to how Laravel handles them.

I think it would be useful to provide both a Get method and a Has method.

Get<T>(string key);
Has(string key);

Questions: A list of questions.

Hi, This project looks great! We are currently using Hangfire and it is pretty great, but it doesn't have the developers full attention, so metrics, reporting, and 3rd party integrations are not easy.

Just a few questions for:

  • Can you have multiple queues: Default, Critical, Events, Email?
  • I don't see any documentation about scale / workers? If I put 100,000 jobs in a queue, how does that get processed?

TimeZone on Scheduler

Describe the bug
Hi There ...
I try to use scheduler in my application that will run the application every midnight.

var provider = app.ApplicationServices;
provider.UseScheduler(scheduler =>
{
        scheduler.Schedule<MidNightProcessService>()
        .Daily();
});

The application (scheduler) runs well but it is not midnight but at 7 in the morning.
Fyi. My TimeZone is Utc + 7

Affected Coravel Feature
Scheduling

Expected behaviour
The Scheduler run in the midnight

Decouple Queue From Scheduler

Right now the queue is part of the scheduler.

Need to remove the queue from the scheduler and, perhaps, create a second Timer in the hosted service class. That second timer would trigger the dequeuing.

This way the scheduler and queue could be used independently of each other.

Distributed Server

What should I do if I want the scheduler to run on a single server on distributed servers? Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.