/// <summary> /// Records that an alert has been sent to a given email address. /// </summary> /// <param name="jobsSet">The jobs set.</param> /// <param name="jobId">The job identifier.</param> /// <param name="emailAddress">The email address.</param> public async Task MarkAlertAsSent(JobsSet jobsSet, int jobId, string emailAddress) { var table = _tableClient.GetTableReference(_alertsSentTable); await table.CreateIfNotExistsAsync(); var entity = new JobAlertSentTableEntity() { PartitionKey = ToAzureKeyString(emailAddress), RowKey = jobId.ToString(), JobsSet = jobsSet.ToString() }; try { var result = table.Execute(TableOperation.InsertOrReplace(entity)); } catch (StorageException ex) { if (ex.Message.Contains("(400) Bad Request")) { LogHelper.Error <AzureTableStorageAlertsRepository>($"Mark job alert for job {jobId} as sent to {emailAddress} returned {ex.RequestInformation.ExtendedErrorInformation.ErrorMessage}", ex); ex.ToExceptionless().Submit(); } else { throw; } } }
public void MarkAlertAsSent(JobsSet jobsSet, int jobId, string emailAddress) { if (!_jobsSent.Contains(jobId)) { _jobsSent.Add(jobId); UniqueJobCount++; } }
/// <summary> /// Initializes a new instance of the <see cref="JobsDataFromApi" /> class. /// </summary> /// <param name="apiBaseUrl">The API base URL.</param> /// <param name="jobsSet">The jobs set.</param> /// <param name="jobAdvertBaseUrl">The job advert base URL.</param> /// <param name="httpClientProvider">A method of getting an <see cref="HttpClient"/> to use for the web API requests</param> /// <param name="jobsCache">A method of caching the API results.</param> /// <exception cref="ArgumentNullException">apiBaseUrl</exception> public JobsDataFromApi(Uri apiBaseUrl, JobsSet jobsSet, Uri jobAdvertBaseUrl, IHttpClientProvider httpClientProvider, IJobCacheStrategy jobsCache) { _apiBaseUrl = apiBaseUrl ?? throw new ArgumentNullException(nameof(apiBaseUrl)); _jobsSet = jobsSet; _jobAdvertBaseUrl = jobAdvertBaseUrl ?? throw new ArgumentNullException(nameof(jobAdvertBaseUrl)); _httpClientProvider = httpClientProvider; _jobsCache = jobsCache; }
public Task MarkAlertAsSent(JobsSet jobsSet, int jobId, string emailAddress) { if (!_jobsSent.Contains(jobId)) { _jobsSent.Add(jobId); UniqueJobCount++; } return(Task.CompletedTask); }
/// <summary> /// Reads full details of an individual job from the specified jobs set. /// </summary> /// <param name="jobsSet">The jobs set.</param> /// <param name="jobId">The job identifier.</param> /// <param name="baseUrl">The base URL.</param> /// <returns></returns> protected async Task <Job> Job(JobsSet jobsSet, string jobId, Uri baseUrl) { var jobsProvider = new JobsDataFromExamine(ExamineManager.Instance.SearchProviderCollection[jobsSet + "Searcher"], new QueryBuilder(new LuceneTokenisedQueryBuilder(), new KeywordsTokeniser(), new LuceneStopWordsRemover(), new WildcardSuffixFilter()), null, new RelativeJobUrlGenerator(baseUrl)); return(await jobsProvider.ReadJob(jobId)); }
/// <summary> /// Gets the job alert settings for a <see cref="JobsSet" /> /// </summary> /// <returns></returns> public JobAlertSettings GetJobAlertsSettings(JobsSet jobsSet) { JobAlertSettings settings = null; var jobAlertsSettingsPages = _umbraco.TypedContentAtXPath("//JobAlerts"); foreach (var jobAlertSettingsPage in jobAlertsSettingsPages) { // Get the jobs set selected in the Umbraco page var selectedJobsSet = umbraco.library.GetPreValueAsString(jobAlertSettingsPage.GetPropertyValue <int>("PublicOrRedeployment_Content")); selectedJobsSet = Regex.Replace(selectedJobsSet.ToUpperInvariant(), "[^A-Z]", String.Empty); var jobsSetForPage = (JobsSet)Enum.Parse(typeof(JobsSet), selectedJobsSet, true); if (jobsSetForPage != jobsSet) { continue; } // Create settings from the page settings = new JobAlertSettings(); settings.NewAlertEmailSubject = jobAlertSettingsPage.GetPropertyValue <string>("NewAlertEmailSubject_Alert_settings"); settings.NewAlertEmailBodyHtml = jobAlertSettingsPage.GetPropertyValue <string>("NewAlertEmailBody_Alert_settings"); settings.AlertEmailSubject = jobAlertSettingsPage.GetPropertyValue <string>("AlertEmailSubject_Alert_settings"); settings.AlertEmailBodyHtml = jobAlertSettingsPage.GetPropertyValue <string>("AlertEmailBody_Alert_settings"); var baseUrl = jobAlertSettingsPage.GetPropertyValue <string>("BaseUrl_Alert_settings"); if (!String.IsNullOrEmpty(baseUrl)) { settings.ChangeAlertBaseUrl = new Uri(new Uri(baseUrl), jobAlertSettingsPage.Url()); } else { settings.ChangeAlertBaseUrl = new Uri(jobAlertSettingsPage.UrlAbsolute()); } var jobAdvertPage = jobAlertSettingsPage.GetPropertyValue <IPublishedContent>("JobAdvertPage_Alert_settings"); if (jobAdvertPage != null) { if (!String.IsNullOrEmpty(baseUrl)) { settings.JobAdvertBaseUrl = new Uri(new Uri(baseUrl), jobAdvertPage.Url()); } else { settings.JobAdvertBaseUrl = new Uri(jobAdvertPage.UrlAbsolute()); } } } return(settings); }
/// <summary> /// Gets the ids of the jobs already sent to a given email address. /// </summary> /// <param name="jobsSet">The jobs set.</param> /// <param name="emailAddress">The email address.</param> /// <returns></returns> public async Task <IList <int> > GetJobsSentForEmail(JobsSet jobsSet, string emailAddress) { // Create the table query. var table = _tableClient.GetTableReference(_alertsSentTable); // Initialize a default TableQuery to retrieve all the entities in the table. var tableQuery = new TableQuery <TableEntity>().Where(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, emailAddress), TableOperators.And, TableQuery.GenerateFilterCondition("JobsSet", QueryComparisons.Equal, jobsSet.ToString())) ); return(await ReadAllResults <int>(table, tableQuery, entity => Int32.Parse(entity.RowKey))); }
/// <summary> /// Gets the job alert settings for a <see cref="JobsSet" /> /// </summary> /// <returns></returns> public JobAlertSettings JobAlertSettings(Uri apiBaseUrl, JobsSet jobsSet) { var request = WebRequest.Create(new Uri($"{apiBaseUrl.ToString().TrimEnd('/')}/umbraco/api/{jobsSet}/jobalertsettings/")); _log.Info($"Requesting job alert settings from {request.RequestUri}"); using (var response = request.GetResponse()) { using (var responseReader = new StreamReader(response.GetResponseStream())) { var responseJson = responseReader.ReadToEnd(); return(JsonConvert.DeserializeObject <JobAlertSettings>(responseJson, new[] { new IHtmlStringConverter() })); } } }
/// <summary> /// Reads jobs matching the specified search query /// </summary> /// <param name="jobsSet">The jobs set.</param> /// <param name="query">The query.</param> /// <param name="baseUrl">The base URL.</param> /// <returns></returns> protected async Task <JobSearchResult> Jobs(JobsSet jobsSet, JobSearchQuery query, Uri baseUrl) { var jobsProvider = new JobsDataFromExamine(ExamineManager.Instance.SearchProviderCollection[jobsSet + "Searcher"], new QueryBuilder(new LuceneTokenisedQueryBuilder(), new KeywordsTokeniser(), new LuceneStopWordsRemover(), new WildcardSuffixFilter()), new SalaryRangeLuceneQueryBuilder(), new RelativeJobUrlGenerator(baseUrl)); var jobs = await jobsProvider.ReadJobs(query); foreach (var job in jobs.Jobs) { // Remove these unnecessary and large fields to significantly reduce the amount that's serialised and sent to the client job.AdvertHtml = null; job.AdditionalInformationHtml = null; job.EqualOpportunitiesHtml = null; } return(jobs); }
private async Task DeleteRecordOfAlertsSent(JobsSet jobsSet, string emailAddress) { // Only remove data if there are no more alerts set up for this email, otherwise we may still send jobs they've already seen var alertsForThisEmail = await GetAlerts(new JobAlertsQuery { JobsSet = jobsSet, EmailAddress = emailAddress }); if (alertsForThisEmail.Any()) { return; } // Delete the record of alerts sent var table = _tableClient.GetTableReference(_alertsSentTable); table.CreateIfNotExistsAsync().Wait(); var tableQuery = new TableQuery <TableEntity>().Where(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, emailAddress), TableOperators.And, TableQuery.GenerateFilterCondition("JobsSet", QueryComparisons.Equal, jobsSet.ToString()))); var alertsSentEntities = table.ExecuteQuery(tableQuery); foreach (var entity in alertsSentEntities) { try { table.Execute(TableOperation.Delete(entity)); } catch (StorageException ex) { if (ex.Message.Contains("(400) Bad Request")) { LogHelper.Error <AzureTableStorageAlertsRepository>($"Delete job alert sent record for job {entity.RowKey} and alert {emailAddress} returned {ex.RequestInformation.ExtendedErrorInformation.ErrorMessage}", ex); ex.ToExceptionless().Submit(); } else { throw; } } } }
private async Task SendAlertsForJobSet(IJobsDataProvider jobsProvider, JobsSet jobsSet, int?frequency, JobAlertSettings alertSettings, bool forceResend) { // No point sending alerts without links to the jobs if (alertSettings.JobAdvertBaseUrl == null) { _log.Error("JobAdvertBaseUrl not found - aborting"); return; } // We need somewhere to get the alerts from... var converter = new JobSearchQueryConverter(ConfigurationManager.AppSettings["TranslateObsoleteJobTypes"]?.ToUpperInvariant() == "TRUE"); var encoder = new JobAlertIdEncoder(converter); IJobAlertsRepository alertsRepo = new AzureTableStorageAlertsRepository(converter, ConfigurationManager.ConnectionStrings["JobAlerts.AzureStorage"].ConnectionString); // We need a way to send the alerts... var configuration = new ConfigurationServiceRegistry(); var emailService = ServiceContainer.LoadService <IEmailSender>(configuration); var sender = new JobAlertsByEmailSender(alertSettings, new HtmlJobAlertFormatter(alertSettings, encoder), emailService); // Get them, sort them and send them _log.Info($"Requesting jobs matching {jobsSet} with frequency {frequency} from Azure Storage"); var alerts = await alertsRepo.GetAlerts(new JobAlertsQuery() { Frequency = frequency, JobsSet = jobsSet }); var alertsGroupedByEmail = GroupAlertsByEmail(alerts); _log.Info($"{alerts.Count()} alerts found for {alertsGroupedByEmail.Count()} email addresses"); foreach (var alertsForAnEmail in alertsGroupedByEmail) { foreach (var alert in alertsForAnEmail) { var jobsSentForThisEmail = forceResend ? new List <int>() : await alertsRepo.GetJobsSentForEmail(alert.JobsSet, alert.Email); await LookupJobsForAlert(jobsProvider, alert, jobsSentForThisEmail); } } _log.Info("Sending alerts"); await sender.SendGroupedAlerts(alertsGroupedByEmail, alertsRepo); }
public Task <IList <int> > GetJobsSentForEmail(JobsSet jobsSet, string emailAddress) { throw new NotImplementedException(); }
/// <summary> /// Jobses the lookup values from API. /// </summary> /// <param name="apiBaseUrl">The API base URL.</param> /// <param name="jobsSet">The jobs set.</param> /// <param name="jobsCache">A method of caching the API results.</param> /// <exception cref="ArgumentNullException">apiBaseUrl</exception> public JobsLookupValuesFromApi(Uri apiBaseUrl, JobsSet jobsSet, IJobCacheStrategy jobsCache) { this._apiBaseUrl = apiBaseUrl ?? throw new ArgumentNullException(nameof(apiBaseUrl)); this._jobsSet = jobsSet; this._jobsCache = jobsCache; }
/// <summary> /// Reads the job types. /// </summary> /// <param name="jobsSet">The jobs set.</param> /// <returns></returns> protected async Task <IList <JobsLookupValue> > ReadJobTypes(JobsSet jobsSet) { var dataSource = new JobsLookupValuesFromExamine(ExamineManager.Instance.SearchProviderCollection[jobsSet + "LookupValuesSearcher"]); return(await dataSource.ReadJobTypes()); }
/// <summary> /// Gets the job alert settings for a <see cref="JobsSet" /> /// </summary> /// <param name="jobsSet">The jobs set.</param> protected JobAlertSettings JobAlertSettings(JobsSet jobsSet) { return(new JobAlertsSettingsFromUmbraco(Umbraco).GetJobAlertsSettings(jobsSet)); }