public static async Task Run(
            [ServiceBusTrigger("atmosphere-face-tagged", AccessRights.Listen, Connection = Settings.SB_CONN_NAME)] string message,
            [ServiceBus("atmosphere-face-cleanup", AccessRights.Send, Connection = Settings.SB_CONN_NAME, EntityType = EntityType.Queue)] ICollector <string> cleanupQueue,
            [ServiceBus("atmosphere-face-training-sent", AccessRights.Send, Connection = Settings.SB_CONN_NAME, EntityType = EntityType.Queue)] ICollector <string> trainingSentQueue,
            [ServiceBus("atmosphere-face-enrich-user", AccessRights.Send, Connection = Settings.SB_CONN_NAME, EntityType = EntityType.Queue)] ICollector <string> enrichQueue,
            TraceWriter log)
        {
            log.Info($"Queue trigger '{nameof(SendFaceForTraining)}' with message: {message}");
            var slackInput = message.FromJson <TaggingMessage>();

            // check if the slack message's votes got to the point that
            // * The required number of people taged face as same person => the image should be submitted to congetive service
            // * Not enough votes => wait for more
            // * Too many votes - edge case, only if two users voted simultaniously
            var votesForSamePerson = await getFaceTagsOnImageCount(slackInput.UserId, slackInput.FaceId);

            log.Info($"Votes for same person was {votesForSamePerson} while required is {REQUIRED_VOTES_FROM_DIFF_USERS}");
            if (votesForSamePerson < REQUIRED_VOTES_FROM_DIFF_USERS)
            {
                log.Info($"Not enough votes for face on image. Requires at least {REQUIRED_VOTES_FROM_DIFF_USERS} different user votes to vote for the same user.");
                return;
            }
            else if (votesForSamePerson > REQUIRED_VOTES_FROM_DIFF_USERS)
            {
                log.Info($"Voting alredy closed for the faceId {slackInput.FaceId}, meaning the image was already submitted.");
                return;
            }

            if (await getFaceTagsCount(slackInput.UserId) > MAX_IMAGES_PER_PERSON)
            {
                log.Info($"Reached limit of images per person. Maximum amount is {MAX_IMAGES_PER_PERSON}. This means no more training required for the person.");
                return;
            }

            // ensure mapping of our identifier of user - SlackId has a mapping to user identifier on Cognetive service
            var user = await getUsersMap(slackInput.UserId);

            if (user == null)
            {
                log.Info($"Creating mapping for slackId and cognitiveId");
                var faceApiMapping = await FaceAPIClient.Call <CreateUserResponse>(
                    $"/persongroups/{Settings.FACE_API_GROUP_NAME}/persons",
                    new { name = slackInput.UserId },
                    log);

                user = new UserMap
                {
                    UserId       = slackInput.UserId,
                    CognitiveUid = faceApiMapping.PersonId
                };
                await saveUsersMap(user);

                enrichQueue.Add(user.ToJson());
                log.Info($"Stored new user map {user.ToJson()}");
            }

            try
            {
                // image submitted only once to congetive when a required number of votes reached
                // once submitted we need to prevent any more voting on slack image
                await FaceAPIClient.Call <dynamic>(
                    $"/persongroups/{Settings.FACE_API_GROUP_NAME}/persons/{user.CognitiveUid}/persistedFaces",
                    new { url = $"{Settings.IMAGES_ENDPOINT}/{Settings.CONTAINER_RECTANGLES}/{slackInput.FaceId}.jpg" },
                    log);

                trainingSentQueue.Add(message);
            }
            catch (InvalidOperationException)
            {
                // something went wrong, probably with image itself (e.g. blured) close voting
                // and remove all taggin info perfored till now
                log.Info($"Going to cleanup tagging for this faceId");
                cleanupQueue.Add(message);
            }
        }