コード例 #1
0
        /// <summary>
        /// Insert a response from AVERT into the store
        /// </summary>
        /// <param name="storageConsistencyMode">consistency to use</param>
        /// <param name="reportHandle">uniquely identifies this report</param>
        /// <param name="responseTime">when the response was received from AVERT</param>
        /// <param name="responseBody">body of the response from AVERT</param>
        /// <param name="entity">AVERT transaction entity to update</param>
        /// <returns>a task that inserts the response into the store</returns>
        public async Task InsertResponse(
            StorageConsistencyMode storageConsistencyMode,
            string reportHandle,
            DateTime responseTime,
            string responseBody,
            IAVERTTransactionEntity entity)
        {
            // check inputs
            if (string.IsNullOrWhiteSpace(reportHandle))
            {
                throw new ArgumentNullException("reportHandle");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            // get the table interface
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.AVERT);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.AVERT, TableIdentifier.AVERTLookup) as ObjectTable;

            // update the entity
            entity.ResponseTime = responseTime;
            entity.ResponseBody = responseBody;

            // update it in the store
            await store.ExecuteOperationAsync(Operation.Replace(lookupTable, reportHandle, reportHandle, entity as AVERTTransactionEntity), storageConsistencyMode.ToConsistencyMode());
        }
コード例 #2
0
        /// <summary>
        /// Delete popular topic
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="timeRange">Time range</param>
        /// <param name="hostAppHandle">Hosting app handle: Master app or client app</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="topicHandle">Topic handle</param>
        /// <param name="topicUserHandle">User handle</param>
        /// <returns>Delete popular topic task</returns>
        public async Task DeletePopularTopic(
            StorageConsistencyMode storageConsistencyMode,
            TimeRange timeRange,
            string hostAppHandle,
            string appHandle,
            string topicHandle,
            string topicUserHandle)
        {
            TopicRankFeedEntity topicRankFeedEntity = new TopicRankFeedEntity()
            {
                AppHandle   = appHandle,
                TopicHandle = topicHandle,
                UserHandle  = topicUserHandle
            };
            var serializedEntity = StoreSerializers.MinimalTopicRankFeedEntitySerialize(topicRankFeedEntity);

            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.PopularTopics);

            Transaction   transaction = new Transaction();
            RankFeedTable topicsTable = this.tableStoreManager.GetTable(ContainerIdentifier.PopularTopics, TableIdentifier.PopularTopicsFeed) as RankFeedTable;
            string        feedKey     = this.GetPopularTopicsFeedKey(timeRange, hostAppHandle);

            transaction.Add(Operation.DeleteIfExists(topicsTable, ContainerIdentifier.PopularTopics.ToString(), feedKey, serializedEntity));

            if (timeRange != TimeRange.AllTime)
            {
                RankFeedTable expirationsTable = this.tableStoreManager.GetTable(ContainerIdentifier.PopularTopics, TableIdentifier.PopularTopicsExpirationsFeed) as RankFeedTable;
                transaction.Add(Operation.DeleteIfExists(expirationsTable, ContainerIdentifier.PopularTopics.ToString(), feedKey, serializedEntity));
            }

            await store.ExecuteTransactionAsync(transaction, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #3
0
        /// <summary>
        /// Insert a new submission to AVERT into the store
        /// </summary>
        /// <param name="storageConsistencyMode">consistency to use</param>
        /// <param name="reportHandle">uniquely identifies this report</param>
        /// <param name="appHandle">uniquely identifies the app that the user is in</param>
        /// <param name="reportType">is the complaint against a user or content?</param>
        /// <param name="requestTime">when the request was submitted to AVERT</param>
        /// <param name="requestBody">body of the request to AVERT</param>
        /// <returns>a task that inserts the submission into the store</returns>
        public async Task InsertSubmission(
            StorageConsistencyMode storageConsistencyMode,
            string reportHandle,
            string appHandle,
            ReportType reportType,
            DateTime requestTime,
            string requestBody)
        {
            // check input
            if (string.IsNullOrWhiteSpace(reportHandle))
            {
                throw new ArgumentNullException("reportHandle");
            }

            // get the table interface
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.AVERT);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.AVERT, TableIdentifier.AVERTLookup) as ObjectTable;

            // create the entity that will be inserted into the table
            AVERTTransactionEntity avertTransactionEntity = new AVERTTransactionEntity()
            {
                ReportHandle = reportHandle,
                AppHandle    = appHandle,
                ReportType   = reportType,
                RequestTime  = requestTime,
                RequestBody  = requestBody,
                ResponseTime = TimeUtils.BeginningOfUnixTime,
                ResponseBody = null
            };

            // insert it
            await store.ExecuteOperationAsync(Operation.Insert(lookupTable, reportHandle, reportHandle, avertTransactionEntity), storageConsistencyMode.ToConsistencyMode());
        }
コード例 #4
0
        /// <summary>
        /// Insert push registrations
        /// </summary>
        /// <param name="storageConsistencyMode">Consistency mode</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="platformType">Platform type</param>
        /// <param name="registrationId">OS registration id</param>
        /// <param name="hubRegistrationId">Hub registration id</param>
        /// <param name="language">Client language</param>
        /// <param name="lastUpdatedTime">Last updated time</param>
        /// <returns>Insert push registration task</returns>
        public async Task InsertPushRegistration(
            StorageConsistencyMode storageConsistencyMode,
            string userHandle,
            string appHandle,
            PlatformType platformType,
            string registrationId,
            string hubRegistrationId,
            string language,
            DateTime lastUpdatedTime)
        {
            PushRegistrationFeedEntity entity = new PushRegistrationFeedEntity()
            {
                UserHandle        = userHandle,
                AppHandle         = appHandle,
                PlatformType      = platformType,
                OSRegistrationId  = registrationId,
                HubRegistrationId = hubRegistrationId,
                Language          = language,
                LastUpdatedTime   = lastUpdatedTime
            };

            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.PushRegistrations);

            FeedTable table     = this.tableStoreManager.GetTable(ContainerIdentifier.PushRegistrations, TableIdentifier.PushRegistrationsFeed) as FeedTable;
            Operation operation = Operation.InsertOrReplace(table, userHandle, appHandle, registrationId, entity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #5
0
        /// <summary>
        /// Insert reply
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="replyHandle">Reply handle</param>
        /// <param name="commentHandle">Comment handle</param>
        /// <param name="topicHandle">Topic handle</param>
        /// <param name="text">Reply text</param>
        /// <param name="language">Reply language</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="createdTime">Created time</param>
        /// <param name="reviewStatus">Review status</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="requestId">Request id associated with the create reply request</param>
        /// <returns>Insert reply task</returns>
        public async Task InsertReply(
            StorageConsistencyMode storageConsistencyMode,
            string replyHandle,
            string commentHandle,
            string topicHandle,
            string text,
            string language,
            string userHandle,
            DateTime createdTime,
            ReviewStatus reviewStatus,
            string appHandle,
            string requestId)
        {
            ReplyEntity replyEntity = new ReplyEntity()
            {
                CommentHandle   = commentHandle,
                TopicHandle     = topicHandle,
                Text            = text,
                Language        = language,
                UserHandle      = userHandle,
                CreatedTime     = createdTime,
                LastUpdatedTime = createdTime,
                AppHandle       = appHandle,
                ReviewStatus    = reviewStatus,
                RequestId       = requestId
            };

            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Replies);

            ObjectTable table     = this.tableStoreManager.GetTable(ContainerIdentifier.Replies, TableIdentifier.RepliesObject) as ObjectTable;
            Operation   operation = Operation.Insert(table, replyHandle, replyHandle, replyEntity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #6
0
        /// <summary>
        /// Query popular topics today
        /// </summary>
        /// <param name="timeRange">Time range</param>
        /// <param name="hostAppHandle">Hosting app handle: Master app or client app</param>
        /// <param name="cursor">Read cursor</param>
        /// <param name="limit">Number of items to return</param>
        /// <returns>Topic feed entities</returns>
        public async Task <IList <ITopicFeedEntity> > QueryPopularTopics(TimeRange timeRange, string hostAppHandle, int cursor, int limit)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.PopularTopics);

            RankFeedTable table   = this.tableStoreManager.GetTable(ContainerIdentifier.PopularTopics, TableIdentifier.PopularTopicsFeed) as RankFeedTable;
            string        feedKey = this.GetPopularTopicsFeedKey(timeRange, hostAppHandle);

            // convert our current API cursor (an int) to a CTStore cursor (a string).  Note that CTStore cursors
            // are offset by 1 from API cursors.  This hack will be removed when we change our API to use string-based
            // cursors.
            string ctCursor;

            if (cursor == 0)
            {
                ctCursor = null;
            }
            else
            {
                ctCursor = (cursor - 1).ToString();
            }

            var result = await store.QueryRankFeedReverseAsync(table, ContainerIdentifier.PopularTopics.ToString(), feedKey, ctCursor, limit);

            var convertedResults = result.Select(item => StoreSerializers.MinimalTopicRankFeedEntityDeserialize(item.ItemKey));

            return(convertedResults.ToList <ITopicFeedEntity>());
        }
コード例 #7
0
        /// <summary>
        /// Updates content moderation entity
        /// </summary>
        /// <param name="storageConsistencyMode">consistency to use</param>
        /// <param name="moderationHandle">uniquely identifies this moderation request</param>
        /// <param name="moderationStatus">Moderation status</param>
        /// <param name="entity"><see cref="IModerationEntity"/> to update</param>
        /// <returns>Content moderation entity update task</returns>
        public async Task UpdateModerationStatus(
            StorageConsistencyMode storageConsistencyMode,
            string moderationHandle,
            ModerationStatus moderationStatus,
            IModerationEntity entity)
        {
            if (string.IsNullOrWhiteSpace(moderationHandle))
            {
                throw new ArgumentNullException("moderationHandle");
            }

            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }

            // get content moderation table
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Moderation);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(
                ContainerIdentifier.Moderation,
                TableIdentifier.ModerationObject) as ObjectTable;

            // update the entity
            entity.ModerationStatus = moderationStatus;

            // update it in the store
            var operation = Operation.Replace(lookupTable, entity.AppHandle, moderationHandle, entity as ModerationEntity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #8
0
        /// <summary>
        /// Insert following activity
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="activityHandle">Activity handle</param>
        /// <param name="activityType">Activity type</param>
        /// <param name="actorUserHandle">Actor user handle</param>
        /// <param name="actedOnUserHandle">Acted on user handle</param>
        /// <param name="actedOnContentType">Acted on content type</param>
        /// <param name="actedOnContentHandle">Acted on content handle</param>
        /// <param name="createdTime">Created time</param>
        /// <returns>Insert activity task</returns>
        public async Task InsertFollowingActivity(
            StorageConsistencyMode storageConsistencyMode,
            string userHandle,
            string appHandle,
            string activityHandle,
            ActivityType activityType,
            string actorUserHandle,
            string actedOnUserHandle,
            ContentType actedOnContentType,
            string actedOnContentHandle,
            DateTime createdTime)
        {
            // Insert an activity into a user's following activities feed
            //
            // PartitionKey: UserHandle
            // FeedKey: AppHandle
            // ItemKey: ActivityHandle (reverse sorted by time). We use LikeHandle, CommentHandle, ReplyHandle, and RelationshipHandle as activity handles
            ActivityFeedEntity activityFeedEntity = new ActivityFeedEntity()
            {
                ActivityHandle       = activityHandle,
                AppHandle            = appHandle,
                ActivityType         = activityType,
                ActorUserHandle      = actorUserHandle,
                ActedOnUserHandle    = actedOnUserHandle,
                ActedOnContentType   = actedOnContentType,
                ActedOnContentHandle = actedOnContentHandle,
                CreatedTime          = createdTime
            };

            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.FollowingActivities);

            FeedTable feedTable = this.tableStoreManager.GetTable(ContainerIdentifier.FollowingActivities, TableIdentifier.FollowingActivitiesFeed) as FeedTable;
            Operation operation = Operation.InsertOrReplace(feedTable, userHandle, appHandle, activityHandle, activityFeedEntity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #9
0
        /// <summary>
        /// Has the reporting user already complained about this user?
        /// </summary>
        /// <param name="appHandle">uniquely identifies the app that the users are in</param>
        /// <param name="reportedUserHandle">uniquely identifies the user who is being reported</param>
        /// <param name="reportingUserHandle">uniquely identifies the user doing the reporting</param>
        /// <returns>true if this user has previously complained about this user</returns>
        public async Task <bool> HasReportingUserReportedUserBefore(string appHandle, string reportedUserHandle, string reportingUserHandle)
        {
            // check the inputs
            if (string.IsNullOrWhiteSpace(appHandle))
            {
                throw new ArgumentNullException("appHandle");
            }
            else if (string.IsNullOrWhiteSpace(reportedUserHandle))
            {
                throw new ArgumentNullException("reportedUserHandle");
            }
            else if (string.IsNullOrWhiteSpace(reportingUserHandle))
            {
                throw new ArgumentNullException("reportingUserHandle");
            }

            // get the table interface
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.UserReports);

            ObjectTable lookupUniquenessTable = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsLookupUniquenessByReportingUser) as ObjectTable;

            // check if the reporting user has previously reported this user
            string       uniquenessKey    = UniquenessObjectKey(reportedUserHandle, reportingUserHandle);
            ObjectEntity uniquenessObject = await store.QueryObjectAsync <ObjectEntity>(lookupUniquenessTable, appHandle, uniquenessKey);

            if (uniquenessObject == null)
            {
                return(false);
            }

            return(true);
        }
コード例 #10
0
        /// <summary>
        /// Insert a new user-generated report of another user into the store
        /// </summary>
        /// <param name="storageConsistencyMode">consistency to use</param>
        /// <param name="reportHandle">uniquely identifies this report</param>
        /// <param name="reportedUserHandle">uniquely identifies the user who is being reported</param>
        /// <param name="reportingUserHandle">uniquely identifies the user doing the reporting</param>
        /// <param name="appHandle">uniquely identifies the app that the user is in</param>
        /// <param name="reason">the complaint against the content</param>
        /// <param name="lastUpdatedTime">when the report was received</param>
        /// <param name="hasComplainedBefore">has the reporting user complained about this user before?</param>
        /// <returns>a task that inserts the report into the store</returns>
        public async Task InsertUserReport(
            StorageConsistencyMode storageConsistencyMode,
            string reportHandle,
            string reportedUserHandle,
            string reportingUserHandle,
            string appHandle,
            ReportReason reason,
            DateTime lastUpdatedTime,
            bool hasComplainedBefore)
        {
            // get all the table interfaces
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.UserReports);

            ObjectTable lookupTable               = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsLookup) as ObjectTable;
            ObjectTable lookupUniquenessTable     = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsLookupUniquenessByReportingUser) as ObjectTable;
            FeedTable   feedByAppTable            = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsRecentFeedByApp) as FeedTable;
            FeedTable   feedByReportedUserTable   = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsRecentFeedByReportedUser) as FeedTable;
            FeedTable   feedByReportingUserTable  = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsRecentFeedByReportingUser) as FeedTable;
            CountTable  countByReportedUserTable  = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsCountByReportedUser) as CountTable;
            CountTable  countByReportingUserTable = this.tableStoreManager.GetTable(ContainerIdentifier.UserReports, TableIdentifier.UserReportsCountByReportingUser) as CountTable;

            // create the two entities that will be inserted into the tables
            UserReportEntity userReportEntity = new UserReportEntity()
            {
                ReportedUserHandle  = reportedUserHandle,
                ReportingUserHandle = reportingUserHandle,
                AppHandle           = appHandle,
                Reason      = reason,
                CreatedTime = lastUpdatedTime
            };

            UserReportFeedEntity userReportFeedEntity = new UserReportFeedEntity()
            {
                ReportHandle        = reportHandle,
                ReportedUserHandle  = reportedUserHandle,
                ReportingUserHandle = reportingUserHandle,
                AppHandle           = appHandle
            };

            // do the inserts and increments as a transaction
            Transaction transaction = new Transaction();

            // the partition key is app handle for all tables so that a transaction can be achieved
            transaction.Add(Operation.Insert(lookupTable, appHandle, reportHandle, userReportEntity));
            transaction.Add(Operation.Insert(feedByAppTable, appHandle, appHandle, reportHandle, userReportFeedEntity));
            transaction.Add(Operation.Insert(feedByReportedUserTable, appHandle, reportedUserHandle, reportHandle, userReportFeedEntity));
            transaction.Add(Operation.Insert(feedByReportingUserTable, appHandle, reportingUserHandle, reportHandle, userReportFeedEntity));

            // if the reporting user has not previously reported this user, then increment counts
            if (!hasComplainedBefore)
            {
                string uniquenessKey = UniquenessObjectKey(reportedUserHandle, reportingUserHandle);
                transaction.Add(Operation.Insert(lookupUniquenessTable, appHandle, uniquenessKey, new ObjectEntity()));
                transaction.Add(Operation.InsertOrIncrement(countByReportedUserTable, appHandle, reportedUserHandle));
                transaction.Add(Operation.InsertOrIncrement(countByReportingUserTable, appHandle, reportingUserHandle));
            }

            // execute the transaction
            await store.ExecuteTransactionAsync(transaction, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #11
0
        /// <summary>
        /// Upgrade the store version number in persistent redis
        /// </summary>
        /// <param name="ctStoreMananger">ctstore manager</param>
        /// <param name="persistentCacheConnectionString">connection string for persistent cache</param>
        /// <returns>true if upgrade is successful</returns>
        private static async Task <bool> UpgradeStoreVersionRedis(CTStoreManager ctStoreMananger, string persistentCacheConnectionString)
        {
            RedisCache redisCachePersistent = new RedisCache(persistentCacheConnectionString);
            CTStore    persistentCacheStore = new CTStore(null, redisCachePersistent);

            ObjectTable versionTable = Table.GetObjectTable(
                ContainerIdentifier.ServiceConfig.ToString(),
                ctStoreMananger.ServiceConfigContainerInitials,
                ctStoreMananger.StoreVersionTableName,
                ctStoreMananger.StoreVersionTableInitials,
                StorageMode.CacheOnly);

            var persistentCacheVersion = await persistentCacheStore.QueryObjectAsync <StoreVersionEntity>(versionTable, ctStoreMananger.StoreVersionKey, ctStoreMananger.StoreVersionKey);

            // if version in store does not match oldVersion, then refuse to upgrade
            if (persistentCacheVersion.Version != oldVersion)
            {
                Console.WriteLine("Version mismatch in persistent Redis: original version in store is {0}", persistentCacheVersion.Version);
                return(false);
            }

            persistentCacheVersion.Version = newVersion;
            var operation = Operation.Replace(versionTable, ctStoreMananger.StoreVersionKey, ctStoreMananger.StoreVersionKey, persistentCacheVersion);

            // perform the insert operation on persistent redis
            await persistentCacheStore.ExecuteOperationAsync(operation, ConsistencyMode.Strong);

            return(true);
        }
コード例 #12
0
        /// <summary>
        /// Provision the contents of the redis caches
        /// </summary>
        /// <param name="persistentCacheConnectionString">connection string for persistent cache</param>
        /// <param name="tableStoreManager">table store manager</param>
        /// <returns>provisioning task</returns>
        private static async Task ProvisionRedisCaches(string persistentCacheConnectionString, CTStoreManager tableStoreManager)
        {
            Console.WriteLine("Provisioning Redis Caches...");

            // insert the store version number into table storage
            var versionEntity = new StoreVersionEntity {
                Version = tableStoreManager.StoreVersionString
            };

            ObjectTable versionTable = Table.GetObjectTable(
                ContainerIdentifier.ServiceConfig.ToString(),
                tableStoreManager.ServiceConfigContainerInitials,
                tableStoreManager.StoreVersionTableName,
                tableStoreManager.StoreVersionTableInitials,
                StorageMode.CacheOnly);
            var operation = Operation.Insert(versionTable, tableStoreManager.StoreVersionKey, tableStoreManager.StoreVersionKey, versionEntity);

            RedisCache redisCachePersistent = new RedisCache(persistentCacheConnectionString);
            CTStore    persistentCache      = new CTStore(null, redisCachePersistent);

            // perform the insert operation on persistent redis
            // note that we only insert the version number into persistent redis,
            // because with volatile redis each time the cache restarts the version number will be lost
            await persistentCache.ExecuteOperationAsync(operation, ConsistencyMode.Strong);
        }
コード例 #13
0
        /// <summary>
        /// Deletes all the Azure tables
        /// </summary>
        /// <param name="azureTableStorageConnectionString">connection string to azure table storage</param>
        /// <returns>delete task</returns>
        private static async Task DeleteAzureTables(string azureTableStorageConnectionString)
        {
            Console.WriteLine("Deleting all tables from Azure Table Store...");

            // Get azure table storage with the give connection string
            AzureTableStorage azureTableStorage = new AzureTableStorage(azureTableStorageConnectionString);

            // Get CTStore using only azure table storage
            CTStore store = new CTStore(azureTableStorage, null);

            // Enumerate all the containers defined
            foreach (ContainerIdentifier containerIdentifier in Enum.GetValues(typeof(ContainerIdentifier)))
            {
                if (!ContainerTableDescriptorProvider.Containers.ContainsKey(containerIdentifier))
                {
                    Console.WriteLine("  " + containerIdentifier.ToString() + " - Descriptor not found");
                    continue;
                }

                // delete each table container
                await store.DeleteContainerAsync(containerIdentifier.ToString());

                Console.WriteLine("  " + containerIdentifier.ToString() + " - Table Container Deleted");
            }

            // clean up the StoreVersion container because it has no descriptor
            await store.DeleteContainerAsync(ContainerIdentifier.ServiceConfig.ToString());

            Console.WriteLine("  " + ContainerIdentifier.ServiceConfig.ToString() + " - Table Container Deleted");
        }
コード例 #14
0
        /// <summary>
        /// Upgrade the store version number in azure table storage
        /// </summary>
        /// <param name="tableStoreManager">table store manager</param>
        /// <param name="azureConnectionString">azure connection string</param>
        /// <returns>true if upgrade is successful</returns>
        private static async Task <bool> UpgradeStoreVersionAzureTables(CTStoreManager tableStoreManager, string azureConnectionString)
        {
            // Get azure table storage with the give connection string
            AzureTableStorage azureTableStorage = new AzureTableStorage(azureConnectionString);

            // Get CTStore using the azure table storage
            CTStore store = new CTStore(azureTableStorage, null);

            ObjectTable versionTable = Table.GetObjectTable(
                ContainerIdentifier.ServiceConfig.ToString(),
                tableStoreManager.ServiceConfigContainerInitials,
                tableStoreManager.StoreVersionTableName,
                tableStoreManager.StoreVersionTableInitials,
                StorageMode.PersistentOnly);

            var currentTableVersion = await azureTableStorage.QueryObjectAsync <StoreVersionEntity>(versionTable, tableStoreManager.StoreVersionKey, tableStoreManager.StoreVersionKey);

            // if version in store does not match oldVersion, then refuse to upgrade
            if (currentTableVersion.Version != oldVersion)
            {
                Console.WriteLine("Version mismatch in Azure table storage: original version in store is {0}", currentTableVersion.Version);
                return(false);
            }

            currentTableVersion.Version = newVersion;
            var operation = Operation.Replace(versionTable, tableStoreManager.StoreVersionKey, tableStoreManager.StoreVersionKey, currentTableVersion);

            // perform the insert on Azure table storage
            await store.ExecuteOperationAsync(operation, ConsistencyMode.Strong);

            return(true);
        }
コード例 #15
0
        /// <summary>
        /// Get store from container identifier
        /// </summary>
        /// <param name="containerIdentifier">Container identifier</param>
        /// <returns>CT store</returns>
        public async Task <CTStore> GetStore(ContainerIdentifier containerIdentifier)
        {
            // refuse to provide the store if the version check fails, or if it has not been executed
            if (this.initialized == false)
            {
                return(null);
            }

            ContainerDescriptor containerDescriptor = ContainerTableDescriptorProvider.Containers[containerIdentifier];
            string azureStorageConnectionString     = await this.connectionStringProvider.GetTablesAzureStorageConnectionString(containerDescriptor.AzureStorageInstanceType);

            string redisConnectionString = await this.connectionStringProvider.GetRedisConnectionString(containerDescriptor.RedisInstanceType);

            string uniqueStoreIdentity = string.Join(":", azureStorageConnectionString, redisConnectionString);

            // cachedStoreObjects is a thread-safe dictionary (ConcurrentDictionary). If uniqueStoreIdentity is not present
            // in cachedStoreObects, try adding it. Since GetStore can be called concurrently by
            // different threads, it is possible for two (or more) threads to attempt inserting uniqueStoreIdentity
            // concurrently in the cachedStoreObjects. That's ok, because the call to TryAdd is guaranteed to be thread-safe.
            // One of the threads will not be able to insert (i.e., TryAdd will return false), but the code will happily execute
            // and fall through to the return statement.
            // This code makes no use of locking on the common path (i.e., reads of cachedStoreObjects).
            if (!this.cachedStoreObjects.ContainsKey(uniqueStoreIdentity))
            {
                AzureTableStorage azureTableStorage = new AzureTableStorage(azureStorageConnectionString);
                azureTableStorage.TableRequestOptions = AzureStorageConfiguration.GetTableRequestOptions();
                RedisCache redisCache = new RedisCache(redisConnectionString);

                CTStore store = new CTStore(azureTableStorage, redisCache);
                this.cachedStoreObjects.TryAdd(uniqueStoreIdentity, store);
            }

            return(this.cachedStoreObjects[uniqueStoreIdentity]);
        }
コード例 #16
0
        /// <summary>
        /// Update following relationship.
        /// Following user : someone who i am following.
        /// </summary>
        /// <param name="storageConsistencyMode">Consistency mode</param>
        /// <param name="relationshipHandle">Relationship handle</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="relationshipUserHandle">Relationship user handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="userRelationshipStatus">User relationship status</param>
        /// <param name="lastUpdatedTime">Last updated time</param>
        /// <param name="readUserRelationshipLookupEntity">Read user relationship lookup entity</param>
        /// <returns>Update following relationship task</returns>
        public async Task UpdateFollowingRelationship(
            StorageConsistencyMode storageConsistencyMode,
            string relationshipHandle,
            string userHandle,
            string relationshipUserHandle,
            string appHandle,
            UserRelationshipStatus userRelationshipStatus,
            DateTime lastUpdatedTime,
            IUserRelationshipLookupEntity readUserRelationshipLookupEntity)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.UserFollowing);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingLookup) as ObjectTable;
            FeedTable   feedTable   = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingFeed) as FeedTable;
            CountTable  countTable  = this.tableStoreManager.GetTable(ContainerIdentifier.UserFollowing, TableIdentifier.FollowingCount) as CountTable;

            await this.UpdateUserRelationship(
                storageConsistencyMode,
                relationshipHandle,
                userHandle,
                relationshipUserHandle,
                appHandle,
                userRelationshipStatus,
                lastUpdatedTime,
                readUserRelationshipLookupEntity,
                store,
                lookupTable,
                feedTable,
                countTable);
        }
コード例 #17
0
        /// <summary>
        /// Update notifications status
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="readActivityHandle">Read activity handle</param>
        /// <param name="readNotificationsStatusEntity">Read notifications status entity</param>
        /// <returns>Update notifications status task</returns>
        public async Task UpdateNotificationsStatus(
            StorageConsistencyMode storageConsistencyMode,
            string userHandle,
            string appHandle,
            string readActivityHandle,
            INotificationsStatusEntity readNotificationsStatusEntity)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Notifications);

            ObjectTable statusTable = this.tableStoreManager.GetTable(ContainerIdentifier.Notifications, TableIdentifier.NotificationsStatus) as ObjectTable;
            CountTable  countTable  = this.tableStoreManager.GetTable(ContainerIdentifier.Notifications, TableIdentifier.NotificationsCount) as CountTable;

            Transaction transaction = new Transaction();

            if (readNotificationsStatusEntity == null)
            {
                NotificationsStatusEntity notificationsStatusEntity = new NotificationsStatusEntity()
                {
                    ReadActivityHandle = readActivityHandle
                };

                transaction.Add(Operation.Insert(statusTable, userHandle, appHandle, notificationsStatusEntity));
            }
            else
            {
                readNotificationsStatusEntity.ReadActivityHandle = readActivityHandle;
                transaction.Add(Operation.Replace(statusTable, userHandle, appHandle, readNotificationsStatusEntity as NotificationsStatusEntity));
            }

            transaction.Add(Operation.InsertOrReplace(countTable, userHandle, appHandle, 0));
            await store.ExecuteTransactionAsync(transaction, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #18
0
        /// <summary>
        /// Insert user topic
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="topicHandle">Topic handle</param>
        /// <returns>Insert user topic task</returns>
        public async Task InsertUserTopic(
            StorageConsistencyMode storageConsistencyMode,
            string userHandle,
            string appHandle,
            string topicHandle)
        {
            TopicFeedEntity topicFeedEntity = new TopicFeedEntity()
            {
                AppHandle   = appHandle,
                TopicHandle = topicHandle,
                UserHandle  = userHandle
            };

            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.UserTopics);

            FeedTable  feedTable  = this.tableStoreManager.GetTable(ContainerIdentifier.UserTopics, TableIdentifier.UserTopicsFeed) as FeedTable;
            CountTable countTable = this.tableStoreManager.GetTable(ContainerIdentifier.UserTopics, TableIdentifier.UserTopicsCount) as CountTable;

            Transaction transaction = new Transaction();

            transaction.Add(Operation.Insert(feedTable, userHandle, appHandle, topicHandle, topicFeedEntity));
            transaction.Add(Operation.Insert(feedTable, userHandle, MasterApp.AppHandle, topicHandle, topicFeedEntity));
            transaction.Add(Operation.InsertOrIncrement(countTable, userHandle, appHandle));
            transaction.Add(Operation.InsertOrIncrement(countTable, userHandle, MasterApp.AppHandle));
            await store.ExecuteTransactionAsync(transaction, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #19
0
        /// <summary>
        /// Query notification
        /// </summary>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="activityHandle">Activity handle</param>
        /// <returns>Activity feed entity</returns>
        public async Task <IActivityFeedEntity> QueryNotification(string userHandle, string appHandle, string activityHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Notifications);

            FeedTable table = this.tableStoreManager.GetTable(ContainerIdentifier.Notifications, TableIdentifier.NotificationsFeed) as FeedTable;

            return(await store.QueryFeedItemAsync <ActivityFeedEntity>(table, userHandle, appHandle, activityHandle));
        }
コード例 #20
0
        /// <summary>
        /// Query like
        /// </summary>
        /// <param name="contentHandle">Content handle</param>
        /// <param name="userHandle">User handle</param>
        /// <returns>Like lookup entity</returns>
        public async Task <ILikeLookupEntity> QueryLike(string contentHandle, string userHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Likes);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.Likes, TableIdentifier.LikesLookup) as ObjectTable;

            return(await store.QueryObjectAsync <LikeLookupEntity>(lookupTable, contentHandle, userHandle));
        }
コード例 #21
0
        /// <summary>
        /// Query app key index
        /// </summary>
        /// <param name="appKey">App key</param>
        /// <returns>App lookup entity</returns>
        public async Task <IAppLookupEntity> QueryAppKeyIndex(string appKey)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.AppKeys);

            ObjectTable table = this.tableStoreManager.GetTable(ContainerIdentifier.AppKeys, TableIdentifier.AppKeysIndex) as ObjectTable;

            return(await store.QueryObjectAsync <AppLookupEntity>(table, appKey, appKey));
        }
コード例 #22
0
        /// <summary>
        /// Query pin
        /// </summary>
        /// <param name="userHandle">User handle</param>
        /// <param name="topicHandle">Topic handle</param>
        /// <returns>Pin lookup entity</returns>
        public async Task <IPinLookupEntity> QueryPin(string userHandle, string topicHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Pins);

            ObjectTable lookupTable = this.tableStoreManager.GetTable(ContainerIdentifier.Pins, TableIdentifier.PinsLookup) as ObjectTable;

            return(await store.QueryObjectAsync <PinLookupEntity>(lookupTable, userHandle, topicHandle));
        }
コード例 #23
0
        /// <summary>
        /// Query popular topics maximum count
        /// </summary>
        /// <param name="timeRange">Time range</param>
        /// <returns>Maximum count of popular topics feeds</returns>
        public async Task <long> QueryPopularTopicsMaxCount(TimeRange timeRange)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.PopularTopics);

            RankFeedTable table = this.tableStoreManager.GetTable(ContainerIdentifier.PopularTopics, TableIdentifier.PopularTopicsFeed) as RankFeedTable;

            return(table.MaxFeedSizeInCache);
        }
コード例 #24
0
        /// <summary>
        /// Update a comment
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="commentHandle">Comment handle</param>
        /// <param name="commentEntity">Comment entity</param>
        /// <returns>Update comment task</returns>
        public async Task UpdateComment(StorageConsistencyMode storageConsistencyMode, string commentHandle, ICommentEntity commentEntity)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Comments);

            ObjectTable table     = this.tableStoreManager.GetTable(ContainerIdentifier.Comments, TableIdentifier.CommentsObject) as ObjectTable;
            Operation   operation = Operation.Replace(table, commentHandle, commentHandle, commentEntity as CommentEntity);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #25
0
        /// <summary>
        /// Delete blob metadata
        /// </summary>
        /// <param name="storageConsistencyMode">Storage consistency mode</param>
        /// <param name="appHandle">App handle</param>
        /// <param name="userHandle">User handle</param>
        /// <param name="blobHandle">Blob handle</param>
        /// <returns>Delete blob metadata task</returns>
        public async Task DeleteBlobMetadata(StorageConsistencyMode storageConsistencyMode, string appHandle, string userHandle, string blobHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Blobs);

            ObjectTable table        = this.tableStoreManager.GetTable(ContainerIdentifier.Blobs, TableIdentifier.BlobsMetadata) as ObjectTable;
            string      partitionKey = this.GetPartitionKey(appHandle, userHandle);
            Operation   operation    = Operation.Delete(table, partitionKey, blobHandle);
            await store.ExecuteOperationAsync(operation, storageConsistencyMode.ToConsistencyMode());
        }
コード例 #26
0
        /// <summary>
        /// Query client config
        /// </summary>
        /// <param name="developerId">Developer id</param>
        /// <param name="clientName">Client name</param>
        /// <returns>Client config entity</returns>
        public async Task <IClientConfigEntity> QueryClientConfig(string developerId, string clientName)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.ClientConfigs);

            ObjectTable clientNameTable = this.tableStoreManager.GetTable(ContainerIdentifier.ClientConfigs, TableIdentifier.ClientConfigsObject) as ObjectTable;
            var         objectKey       = this.GetClientConfigsObjectKey(developerId, clientName);

            return(await store.QueryObjectAsync <ClientConfigEntity>(clientNameTable, objectKey, objectKey));
        }
コード例 #27
0
        /// <summary>
        /// Query client name from ClientNamesFeed in AppKey container
        /// </summary>
        /// <param name="appKey">App key</param>
        /// <returns>Client names</returns>
        public async Task <IList <IClientNamesFeedEntity> > QueryClientNames(string appKey)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.AppKeys);

            FeedTable table  = this.tableStoreManager.GetTable(ContainerIdentifier.AppKeys, TableIdentifier.ClientNamesFeed) as FeedTable;
            var       result = await store.QueryFeedAsync <ClientNamesFeedEntity>(table, appKey, this.tableStoreManager.DefaultFeedKey, null, int.MaxValue);

            return(result.ToList <IClientNamesFeedEntity>());
        }
コード例 #28
0
        /// <summary>
        /// Query user apps
        /// </summary>
        /// <param name="userHandle">User handle</param>
        /// <returns>Apps used by user</returns>
        public async Task <IList <IAppFeedEntity> > QueryUserApps(string userHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Users);

            FeedTable indexTable = this.tableStoreManager.GetTable(ContainerIdentifier.Users, TableIdentifier.UserAppsFeed) as FeedTable;
            var       result     = await store.QueryFeedAsync <AppFeedEntity>(indexTable, userHandle, this.tableStoreManager.DefaultFeedKey, null, int.MaxValue);

            return(result.ToList <IAppFeedEntity>());
        }
コード例 #29
0
        /// <summary>
        /// Query user
        /// </summary>
        /// <param name="userHandle">User handle</param>
        /// <param name="appHandle">App handle</param>
        /// <returns>User profile entity</returns>
        public async Task <IUserProfileEntity> QueryUserProfile(string userHandle, string appHandle)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Users);

            ObjectTable       profilesTable     = this.tableStoreManager.GetTable(ContainerIdentifier.Users, TableIdentifier.UserProfilesObject) as ObjectTable;
            UserProfileEntity userProfileEntity = await store.QueryObjectAsync <UserProfileEntity>(profilesTable, userHandle, appHandle);

            return(userProfileEntity);
        }
コード例 #30
0
        /// <summary>
        /// Query likes for a content
        /// </summary>
        /// <param name="contentHandle">Content handle</param>
        /// <param name="cursor">Read cursor</param>
        /// <param name="limit">Number of items to return</param>
        /// <returns>List of like feed entities</returns>
        public async Task <IList <ILikeFeedEntity> > QueryLikes(string contentHandle, string cursor, int limit)
        {
            CTStore store = await this.tableStoreManager.GetStore(ContainerIdentifier.Likes);

            FeedTable feedTable = this.tableStoreManager.GetTable(ContainerIdentifier.Likes, TableIdentifier.LikesFeed) as FeedTable;
            var       result    = await store.QueryFeedAsync <LikeFeedEntity>(feedTable, contentHandle, this.tableStoreManager.DefaultFeedKey, cursor, limit);

            return(result.ToList <ILikeFeedEntity>());
        }