Skip to content

Commit

Permalink
R10 samples (microsoft#2706)
Browse files Browse the repository at this point in the history
* CardAction image alt text and some cleanup (microsoft#2570)

* Cards bot OAuthCard cleanup

* dotnet: SuggestedActionsBot CardAction images and alt text

* javascript: SuggestedActionsBot CardAction images and alt text

* Add image_alt_text to python SuggestedActions CardActions (microsoft#2587)

* Axsuarez/welcome with activity locale (microsoft#2593)

* Updated welcomeBot to display the locale in the conversationupdate activity.

* Update welcome_user_bot.py

Touched file to trigger another build

Co-authored-by: Gabo Gilabert <[email protected]>

* Updated WelcomeBot projects with info on how to use the activity's locale (microsoft#2591)

* dotnet updates:
Updated WelcomeUser sample with information on how to get the locale for the incoming activity.
Added some missing canellationTokens

* JS update:
Updated welcomeBot to display the locale in the conversationupdate activity.
Applied consistent quotes to the messages being sent.

* Added single quote to the method name.

* Python: Merged dotnet readme changes (microsoft#2592)

* JS: README parity (microsoft#2624)

* Add dotnet immediate accept adapter sample to experimental (microsoft#2619)

* Add ImmediateAcceptAdapter to experimental

* readme update

* Address feadback

* Javascript: Add iFrame based Task Module sample (microsoft#2647)

* Javascript: iFrame for 54.teams-task-module

* Javascript: Suppressed method not allowed error due to for post to static page.

* Update samples/javascript_nodejs/54.teams-task-module/models/taskmoduleuiconstants.js

Co-authored-by: Michael Richardson <[email protected]>

* Update samples/javascript_nodejs/54.teams-task-module/models/taskmoduleresponsefactory.js

Co-authored-by: Michael Richardson <[email protected]>

* Update samples/javascript_nodejs/54.teams-task-module/index.js

Co-authored-by: Michael Richardson <[email protected]>

* Update samples/javascript_nodejs/54.teams-task-module/bots/teamsTaskModuleBot.js

Co-authored-by: Michael Richardson <[email protected]>

* Update samples/javascript_nodejs/54.teams-task-module/bots/teamsTaskModuleBot.js

Co-authored-by: Michael Richardson <[email protected]>

Co-authored-by: Michael Richardson <[email protected]>

* TS teams messaging extensions search sample (microsoft#2629)

* TS Teams conversation bot sample (microsoft#2627)

* Zerryth/dotenv before bot (microsoft#2635)

* 03.welcome-users - moved dotenv to top

* 05.multi-turn-prompt - moved usage dotenv to top

* 06.using-cards - moved usage dotenv to top

* 07.using-adaptive-cards - moved usage dotenv to top

* samples 11-21 - moved usage dotenv to top

* samples 23-81, except 40 & 80 - moved usage dotenv to top

* LG samples - moved usage dotenv to top

* Python: Add iFrame based Task Module sample (microsoft#2670)

* Python: 54.teams-task-module

* Python: 54.teams-task-module, cleaned up code, added comments.

* Python: Suppressed error from form post to static page.

* Corrected manifest.json icon names

* Python: Teams Task sample, manually serializing CardAction value.

* TS Teams start new thread in channel sample (microsoft#2628)

* TS Teams start new thread in channel sample

* Updated .env file

* added replace dependency in package.json

* TS Teams messaging extensions action sample (microsoft#2630)

* Update js version to 4.10.1 and fix eslint issues (microsoft#2705)

* Update typescript samples to 4.10.1

* Update javascript to 4.10.1 and fix eslint issues

* Update dotnet sample 3, 6, and 8 sdk vesrions (microsoft#2707)

Co-authored-by: Axel Suárez <[email protected]>
Co-authored-by: Gabo Gilabert <[email protected]>
Co-authored-by: tracyboehrer <[email protected]>
Co-authored-by: Michael Richardson <[email protected]>
Co-authored-by: Steven Kanberg <[email protected]>
Co-authored-by: Ashley Finafrock <[email protected]>
  • Loading branch information
7 people authored Sep 1, 2020
1 parent 241834e commit 9c93ceb
Show file tree
Hide file tree
Showing 260 changed files with 10,229 additions and 839 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
using Microsoft.Bot.Schema;
using System;
using System.Collections.Concurrent;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;

namespace ImmediateAcceptBot.BackgroundQueue
{
/// <summary>
/// Singleton queue, used to transfer an ActivityWithClaims to the <see cref="HostedActivityService"/>.
/// </summary>
public class ActivityTaskQueue : IActivityTaskQueue
{
private SemaphoreSlim _signal = new SemaphoreSlim(0);
private ConcurrentQueue<ActivityWithClaims> _activities = new ConcurrentQueue<ActivityWithClaims>();

/// <summary>
/// Enqueue an Activity, with Claims, to be processed on a background thread.
/// </summary>
/// <remarks>
/// It is assumed these claims have been authenticated via JwtTokenValidation.AuthenticateRequest
/// before enqueueing.
/// </remarks>
/// <param name="claimsIdentity">Authenticated <see cref="ClaimsIdentity"/> used to process the
/// activity.</param>
/// <param name="activity"><see cref="Activity"/> to be processed.</param>
public void QueueBackgroundActivity(ClaimsIdentity claimsIdentity, Activity activity)
{
if (claimsIdentity == null)
{
throw new ArgumentNullException(nameof(claimsIdentity));
}

if (activity == null)
{
throw new ArgumentNullException(nameof(activity));
}

_activities.Enqueue(new ActivityWithClaims { ClaimsIdentity = claimsIdentity, Activity = activity});
_signal.Release();
}

/// <summary>
/// Wait for a signal of an enqueued Activity with Claims to be processed.
/// </summary>
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
/// <returns>An ActivityWithClaims to be processed.
/// </returns>
/// <remarks>It is assumed these claims have already been authenticated via JwtTokenValidation.AuthenticateRequest.</remarks>
public async Task<ActivityWithClaims> WaitForActivityAsync(CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);

ActivityWithClaims dequeued;
_activities.TryDequeue(out dequeued);

return dequeued;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
using System.Security.Claims;
using Microsoft.Bot.Schema;

namespace ImmediateAcceptBot.BackgroundQueue
{
/// <summary>
/// Activity with Claims which should already have been authenticated via JwtTokenValidation.AuthenticateRequest.
/// </summary>
public class ActivityWithClaims
{
/// <summary>
/// <see cref="ClaimsIdentity"/> retrieved from a call to JwtTokenValidation.AuthenticateRequest.
/// <seealso cref="ImmediateAcceptAdapter"/>
/// </summary>
public ClaimsIdentity ClaimsIdentity { get; set; }

/// <summary>
/// <see cref="Activity"/> which is to be processed.
/// </summary>
public Activity Activity { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace ImmediateAcceptBot.BackgroundQueue
{
/// <summary>
/// <see cref="BackgroundService"/> implementation used to process activities with claims.
/// <see href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.hosting.backgroundservice">More information.</see>
/// </summary>
public class HostedActivityService : BackgroundService
{
private readonly ILogger<HostedTaskService> _logger;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private readonly ConcurrentDictionary<ActivityWithClaims, Task> _activitiesProcessing = new ConcurrentDictionary<ActivityWithClaims, Task>();
private IActivityTaskQueue _activityQueue;
private readonly ImmediateAcceptAdapter _adapter;
private readonly IBot _bot;
private readonly int _shutdownTimeoutSeconds;

/// <summary>
/// Create a <see cref="HostedActivityService"/> instance for processing Bot Framework Activities\
/// on background threads.
/// </summary>
/// <remarks>
/// It is important to note that exceptions on the background thread are only logged in the <see cref="ILogger"/>.
/// </remarks>
/// <param name="config"><see cref="IConfiguration"/> used to retrieve ShutdownTimeoutSeconds from appsettings.</param>
/// <param name="bot">IBot which will be used to process Activities.</param>
/// <param name="adapter"><see cref="ImmediateAcceptAdapter"/> used to process Activities. </param>
/// <param name="activityTaskQueue"><see cref="IActivityTaskQueue"/>Queue of activities to be processed. This class
/// contains a semaphore which the BackgroundService waits on to be notified of activities to be processed.</param>
/// <param name="logger">Logger to use for logging BackgroundService processing and exception information.</param>
public HostedActivityService(IConfiguration config, IBot bot, ImmediateAcceptAdapter adapter, IActivityTaskQueue activityTaskQueue, ILogger<HostedTaskService> logger)
{
if (config == null)
{
throw new ArgumentNullException(nameof(config));
}

if (bot == null)
{
throw new ArgumentNullException(nameof(bot));
}

if (adapter == null)
{
throw new ArgumentNullException(nameof(adapter));
}

if (activityTaskQueue == null)
{
throw new ArgumentNullException(nameof(activityTaskQueue));
}

_shutdownTimeoutSeconds = config.GetValue<int>("ShutdownTimeoutSeconds");
_activityQueue = activityTaskQueue;
_bot = bot;
_adapter = adapter;
_logger = logger ?? NullLogger<HostedTaskService>.Instance;
}

/// <summary>
/// Called by BackgroundService when the hosting service is shutting down.
/// </summary>
/// <param name="stoppingToken"><see cref="CancellationToken"/> sent from BackgroundService for shutdown.</param>
/// <returns>The Task to be executed asynchronously.</returns>
public override async Task StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Queued Hosted Service is stopping.");

// Obtain a write lock and do not release it, preventing new tasks from starting
if (_lock.TryEnterWriteLock(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)))
{
// Wait for currently running tasks, but only n seconds.
await Task.WhenAny(Task.WhenAll(_activitiesProcessing.Values), Task.Delay(TimeSpan.FromSeconds(_shutdownTimeoutSeconds)));
}

await base.StopAsync(stoppingToken);
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation($"Queued Hosted Service is running.{Environment.NewLine}");

await BackgroundProcessing(stoppingToken);
}

private async Task BackgroundProcessing(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var activityWithClaims = await _activityQueue.WaitForActivityAsync(stoppingToken);
if (activityWithClaims != null)
{
try
{
// The read lock will not be acquirable if the app is shutting down.
// New tasks should not be starting during shutdown.
if (_lock.TryEnterReadLock(500))
{
// Create the task which will execute the work item.
var task = GetTaskFromWorkItem(activityWithClaims, stoppingToken)
.ContinueWith(t =>
{
// After the work item completes, clear the running tasks of all completed tasks.
foreach (var task in _activitiesProcessing.Where(tsk => tsk.Value.IsCompleted))
{
_activitiesProcessing.TryRemove(task.Key, out Task removed);
}
}, stoppingToken);

_activitiesProcessing.TryAdd(activityWithClaims, task);
}
else
{
_logger.LogError("Work item not processed. Server is shutting down.", nameof(BackgroundProcessing));
}
}
finally
{
_lock.ExitReadLock();
}
}
}
}

private Task GetTaskFromWorkItem(ActivityWithClaims activityWithClaims, CancellationToken stoppingToken)
{
// Start the work item, and return the task
return Task.Run(
async () =>
{
try
{
await _adapter.ProcessActivityAsync(activityWithClaims.ClaimsIdentity, activityWithClaims.Activity, _bot.OnTurnAsync, stoppingToken);
}
catch (Exception ex)
{
// Bot Errors should be processed in the Adapter.OnTurnError.
_logger.LogError(ex, "Error occurred executing WorkItem.", nameof(HostedActivityService));
}
}, stoppingToken);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
using Microsoft.Bot.Schema;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;

namespace ImmediateAcceptBot.BackgroundQueue
{
/// <summary>
/// Interface for a class used to transfer an ActivityWithClaims to the <see cref="HostedActivityService"/>.
/// </summary>
public interface IActivityTaskQueue
{
/// <summary>
/// Enqueue an Activity, with Claims, to be processed on a background thread.
/// before enqueueing.
/// </summary>
/// <remarks>It is assumed these claims have been authenticated via JwtTokenValidation.AuthenticateRequest.</remarks>
/// <param name="claimsIdentity">Authenticated <see cref="ClaimsIdentity"/> used to process the
/// activity.</param>
/// <param name="activity"><see cref="Activity"/> to be processed.</param>
void QueueBackgroundActivity(ClaimsIdentity claimsIdentity, Activity activity);

/// <summary>
/// Wait for a signal of an enqueued Activity with Claims to be processed.
/// </summary>
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
/// <returns>An ActivityWithClaims to be processed.</returns>
/// <remarks>It is assumed these claims have already been authenticated.</remarks>
Task<ActivityWithClaims> WaitForActivityAsync(CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace ImmediateAcceptBot.BackgroundQueue
{
/// <summary>
/// Singleton queue, used to transfer a workitem to the <see cref="HostedTaskService"/>.
/// </summary>
public class BackgroundTaskQueue : IBackgroundTaskQueue
{
private ConcurrentQueue<Func<CancellationToken, Task>> _workItems = new ConcurrentQueue<Func<CancellationToken, Task>>();
private SemaphoreSlim _signal = new SemaphoreSlim(0);

/// <summary>
/// Enqueue a work item to be processed on a background thread.
/// </summary>
/// <param name="workItem">The work item to be enqueued for execution, is defined as
/// a function which takes a cancellation token.</param>
public void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem)
{
if (workItem == null)
{
throw new ArgumentNullException(nameof(workItem));
}

_workItems.Enqueue(workItem);
_signal.Release();
}

/// <summary>
/// Wait for a signal of an enqueued work item to be processed.
/// </summary>
/// <param name="cancellationToken">CancellationToken used to cancel the wait.</param>
/// <returns>A function taking a cacnellation token, which needs to be processed.
/// </returns>
public async Task<Func<CancellationToken, Task>> DequeueAsync(CancellationToken cancellationToken)
{
await _signal.WaitAsync(cancellationToken);

Func<CancellationToken, Task> dequeued;
_workItems.TryDequeue(out dequeued);
return dequeued;
}
}
}
Loading

0 comments on commit 9c93ceb

Please sign in to comment.