Sitecore Task Scheduling With Time Period Exception - sitecore

I have a number of scheduled tasks set up in Sitecore. Some run every 15 mins others every few hours.
An example config:
<sitecore>
<scheduling>
<agent type="Acme.Tasks.SitemapProducts, AcmeSitecore" method="Run" interval="00:15:00" site="website">
<param desc="filename">~/products.xml</param>
<param desc="Site">website</param>
<param desc="HasVariants">false</param>
</agent>
</scheduling>
</sitecore>
This runs a task that builds an xml file every 15 mins and is working fine. However I now want to stop this task from running between certain times on certain days. Is there any way for me to add this via config?

No. There is no way of doing this via config only.
What you can do is to pass extra parameters to your scheduled task and set start and end time. And then in your scheduled task code just check if current time is between start and end time.
The job will be executed but it will not generate new xml.
<sitecore>
<scheduling>
<agent type="Acme.Tasks.SitemapProducts, AcmeSitecore" method="Run" interval="00:15:00" site="website">
<param desc="filename">~/products.xml</param>
<param desc="Site">website</param>
<param desc="HasVariants">false</param>
<StartTime>08:00</StartTime>
<Endtime>21:00</Endtime>
</agent>
</scheduling>
</sitecore>
Code should be something like this (not tested):
public class SitemapProducts
{
public string StartTime { get; set; }
public string EndTime { get; set; }
public void Run()
{
if (!string.IsNullOrEmpty(StartTime) && DateTime.Now.ToString("HH:mm") < StartTime)
{
return;
}
if (!string.IsNullOrEmpty(EndTime) && DateTime.Now.ToString("HH:mm") > EndTime)
{
return;
}
}

Related

GCP Pub/Sub: Acknowledgement deadline doesn't work when reading messages

Creating a subscription on GCP Pub Sub with "Acknowledgement deadline" set as its max value (600 seconds), my java client in spring boot, keeps receiving messages every 60 seconds in case the task is still running.
pub/sub subscription
We have a simple consumer very similar to this:
https://spring.io/guides/gs/messaging-gcp-pubsub/
We need to perform operations which can run for some minutes each, but even setting 600 seconds, if the task hasn't finished after 60 seconds, the message arrives again.
Doesn't someone experienced something similar?
Thanks
Update:
These are the main dependencies:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.10.RELEASE</version>
</parent>
<spring-cloud-gcp.version>1.2.6.RELEASE</spring-cloud-gcp.version>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
And this is the setup in the consumer (it's exactly as the spring boot guide linked above explains):
#Bean
public PubSubInboundChannelAdapter messageChannelAdapter(
#Qualifier("pubsubInputChannel") MessageChannel inputChannel,
PubSubTemplate pubSubTemplate) {
LOGGER.info("pubsubInputChannel");
PubSubInboundChannelAdapter adapter =
new PubSubInboundChannelAdapter(pubSubTemplate, subscription);
adapter.setOutputChannel(inputChannel);
adapter.setAckMode(AckMode.AUTO_ACK);
return adapter;
}
#Bean
public MessageChannel pubsubInputChannel() {
return new DirectChannel();
}
#Bean
#ServiceActivator(inputChannel = "pubsubInputChannel")
public MessageHandler messageReceiver() {
return message -> {
String json = new String((byte[]) message.getPayload());
LOGGER.info("Message arrived! Payload: " + json);
//Main code here
//Operations might take some minutes to be finished
};
}

Azure Webjobs - Use INameResolver with TimerTrigger Function

I've tried to configure a job with a simple function with a TimerTrigger.
public class Processor
{
/// <summary>
/// Initializes a new instance of the <see cref="Processor"/> class.
/// </summary>
public Processor()
{
}
/// <summary>
/// Process the Leads to Marketo.
/// </summary>
[Disable("Processor.Disable")]
public async Task ProcessMessages([TimerTrigger("%Processor.TimerTrigger%")] TimerInfo timerInfo, TextWriter log)
{
// TODO : remove
await Task.FromResult(0);
}
}
My settings are defined in my app.config file:
<add key="Processor.TimerTrigger" value="00:01:00" />
<add key="Processor.Disable" value="false" />
When Starting my webjob, I've configure the job to use INameResolver and timertrigger:
static void Main()
{
// Configure the job host
var config = new JobHostConfiguration
{
NameResolver = new ConfigNameResolver() // Resolve name from the config file.
};
config.UseTimers();
var host = new JobHost(config);
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
When executing the line host.RunAndBlock(), I've got this exception :
Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException: Error indexing method 'ProcessMessages' ---> System.FormatException: String was not recognized as a valid TimeSpan.
I've put a break point in the class that implements the INameResolver interface but never hit.
Is there any way to configure a NameResolver with TimerTrigger ?
Thanks.
TimerTrigger does not currently support INameResolver. Please open an issue in the public repo here and we'll add that support. The other extension bindings support INameResolver. If it's important to you, we can get out a pre-release build for you to use/verify ahead of the actual next release.
Confirmation that INameResolver is now supported in Timer Triggers using the technique in the original question and a resolver that looks like this:
public class ConfigNameResolver : INameResolver
{
public string Resolve(string name)
{
return ConfigurationManager.AppSettings.Get(name);
}
}

How do you create a Sitecore pipeline processor that runs when a new item is upload to the Media Library

I would like to build a Sitecore pipeline processor that would grab the ID of a media item when it is uploaded and save that ID to an existing custom database that is used by a third-party application.
I have been unable to locate any How-to or examples on how to do this?
I am using Sitecore 8.0 Update 5 and an MVC structure for my code.
You can check in the uiUpload pipeline, but that will not fire for programatically created items, i.e. it will only fire when a user uploads an item via the CMS interface.
Create a new processor class:
public class ExternalSystemProcessor
{
public void Process(UploadArgs args)
{
foreach (Item file in args.UploadedItems.Where(file => file.Paths.IsMediaItem))
{
// Custom code here
SaveToExternalSystem(file.ID);
}
}
}
And then patch the in after the default save processor:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/" xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<processors>
<uiUpload>
<processor type="MyProject.Custom.Pipelines.ExternalSystemProcessor, MyProject.Custom" mode="on"
patch:after="*[#type='Sitecore.Pipelines.Upload.Save, Sitecore.Kernel']" />
</uiUpload>
</processors>
</sitecore>
</configuration>
I don't remember any pipeline that would be executed when a new item is uploaded to media library, but you should be able to use item:created event.
Just check if the item from the args (ItemCreatedEventArgs) is media item and execute your code.
public void OnItemCreated(object sender, EventArgs args)
{
var createdArgs = Event.ExtractParameter(args, 0) as ItemCreatedEventArgs;
if (createdArgs != null)
{
if (createdArgs.Item != null)
{
...
}
}
}

asmx webservice error on server 2008 r2 64bit

We have an asmx web service that works fine on a 32bit windows server 2008 but when it is hosted on a 64bit server 2008 r2 machine it gives a "Index was outside the bounds of the array." when trying to access the javascript files for the service:
http://www.site.com/Service.asmx/js outputs "Index was outside the bounds of the array." only when hosted in 64bit
Here is what the service code looks like:
[WebService(Namespace = "http://www.company.com")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class Saver : WebService
{
/// <summary>A web service to save a set of ScheduleEntryProperties objects.</summary>
[WebMethod]
public string SaveEntries(Entry[] entries, object start, object end, string assignmentIDs, string deptID, string useCodes)
{
...
}
And the Entry object:
[Serializable]
public class Entry
{
public Entry()
{
}
public Entry(object assignmentID, object date, object hours, object text)
{
AssignmentID = assignmentID;
Date = date;
Hours = hours;
Text = text;
}
public object Date;
public object AssignmentID;
public object Text;
public object Hours;
}
Any ideas?
Turns out this has to do with IIS 7.5 <system.webServer /> config section and handler for .axmx that was defined as
<add name="*.asmx_*" path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" preCondition="integratedMode,runtimeVersionv2.0" />
all that was needed was to remove preCondition="integratedMode,runtimeVersionv2.0" and it cleared up the index out of bounds error.

ASP.NET Universal Providers - Roleprovider does not cache roles in cookie

Ironically my role provider does not cache the roles in a cookie anymore. That was working earlier. Unfortunately i have noticed that only now, so i cannot say what causes the problem. But i think it has to do with the update to the new version 1.2 of the universal providers (released on 16th august).
My config for the roleprovider looks like:
<roleManager enabled="true" cacheRolesInCookie="true" cookieName="X_Roles"
cookiePath="/" cookieProtection="All" cookieRequireSSL="true" cookieSlidingExpiration="true" cookieTimeout="1440"
createPersistentCookie="false" domain="" maxCachedResults="25" defaultProvider="XManager_RoleProvider">
<providers>
<clear/>
<add name="XManager_RoleProvider" type="ManagersX.XManager_RoleProvider, AssemblyX"
connectionStringName="XEntities" applicationName="/" rolesTableName="Roles" roleMembershipsTableName="Users_Roles"/>
</providers>
</roleManager>
Everything is working fine with the rolemanager (loginviews, menu with sitemaptrimming etc.), but it is only not caching the roles anymore. The membership provider, sessionstate etc. are also working fine and the cookies of them are set correctly.
All properties of the static Roles-class are correctly set and everything in Httpcontext (IsSecureConnection etc.) is also correct.
The roles cookie was set earlier, but not anymore. I hope anybody can help me with my problem.
Thanks in advance.
Best Regards,
HeManNew
UPDATE:
Has nobody got the same problem or a tip for me, please?
Below are the details of the Custom Role Provider I wrote that uses proper caching and doesn't hit the database on each page load.
============= My Code-Behind file ===============
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.Caching;
using System.Web.Security;
namespace MyProject.Providers
{
public class CustomRoleProvider : RoleProvider
{
#region Properties
private static readonly object LockObject = new object();
private int _cacheTimeoutInMinutes = 0;
#endregion
#region Overrides of RoleProvider
public override void Initialize(string name, NameValueCollection config)
{
// Set Properties
ApplicationName = config["applicationName"];
_cacheTimeoutInMinutes = Convert.ToInt32(config["cacheTimeoutInMinutes"]);
// Call base method
base.Initialize(name, config);
}
/// <summary>
/// Gets a value indicating whether the specified user is in the specified role for the configured applicationName.
/// </summary>
/// <returns>
/// true if the specified user is in the specified role for the configured applicationName; otherwise, false.
/// </returns>
/// <param name="username">The user name to search for.</param><param name="roleName">The role to search in.</param>
public override bool IsUserInRole(string username, string roleName)
{
// Get Roles
var userRoles = GetRolesForUser(username);
// Return if exists
return userRoles.Contains(roleName);
}
/// <summary>
/// Gets a list of the roles that a specified user is in for the configured applicationName.
/// </summary>
/// <returns>
/// A string array containing the names of all the roles that the specified user is in for the configured applicationName.
/// </returns>
/// <param name="username">The user to return a list of roles for.</param>
public override string[] GetRolesForUser(string username)
{
// Return if User is not authenticated
if (!HttpContext.Current.User.Identity.IsAuthenticated) return null;
// Return if present in Cache
var cacheKey = string.format("UserRoles_{0}", username);
if (HttpRuntime.Cache[cacheKey] != null) return (string[]) HttpRuntime.Cache[cacheKey];
// Vars
var userRoles = new List<string>();
var sqlParams = new List<SqlParameter>
{
new SqlParameter("#ApplicationName", ApplicationName),
new SqlParameter("#UserName", username)
};
lock (LockObject)
{
// Run Stored Proc << Replace this block with your own Database Call Methods >>
using (IDataReader dr =
BaseDatabase.ExecuteDataReader("aspnet_UsersInRoles_GetRolesForUser", sqlParams.ToArray(),
Constants.DatabaseConnectionName) as SqlDataReader)
{
while (dr.Read())
{
userRoles.Add(dr["RoleName"].ToString());
}
}
}
// Store in Cache and expire after set minutes
HttpRuntime.Cache.Insert(cacheKey, userRoles.ToArray(), null,
DateTime.Now.AddMinutes(_cacheTimeoutInMinutes), Cache.NoSlidingExpiration);
// Return
return userRoles.ToArray();
}
/// <summary>
/// Gets or sets the name of the application to store and retrieve role information for.
/// </summary>
/// <returns>
/// The name of the application to store and retrieve role information for.
/// </returns>
public override sealed string ApplicationName { get; set; }
// I skipped the other methods as they do not apply to this scenario
#endregion
}
}
============= End of My Code-Behind file ===============
============= My Web.Config file =======================
<roleManager enabled="true" defaultProvider="CustomRoleManager">
<providers>
<clear />
<add name="SqlRoleManager" type="System.Web.Security.SqlRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication"/>
<add name="CustomRoleManager" type="MyProject.Providers.CustomRoleProvider" connectionStringName="AspnetDbConnection" applicationName="MyApplication" cacheTimeoutInMinutes="30" />
</providers>
</roleManager>
============= End of My Web.Config file ================
The cache is set to expire automatically after every 30 minutes. You can modify this as you deem fit.
Cheers.
I was having the same issue, but I was able to find a MS KB article that seems to have fixed it. I installed the patch and the cookie reappeared.
http://support.microsoft.com/kb/2750147
See the section: ASP.Net Issue 4.
Hopefully that helps someone else!