Giter Club home page Giter Club logo

ar.secondround's Introduction

Overview

FMGSuite is an Automation Marketing platform for Finacial Advisors in the US. Many financial advisors have already used another CRM system to manage their customer information. In order for them to enter FMGSuite, we need an integration system to synchronize the customer list from the third party system to our FMG system. Let's start with Salesforce, one of the most popular CRM system on the market now.

There are 2 main entities that we need to sync from the

  • Groups (Topics in Salesforce)
  • Contacts (Customers)

We chose to write it in Lambda to reduce the maintenance cost and make use of the auto-scaling feature. This repo contains a Lambda code of the above 2 workers.

Your task is to review and detect any problems with the code. You don't have to detect any problems with the business logic or the typo because this is just the sample code. You are also expected to give the solution to for those problems.

Instructions

  • Clone this repo to your local computer
  • Push this repo to your personal Github account
  • Review the code and detect any problems
  • For each problem, create a Github issue on your cloned repo and describe the details, including
    • Place in code
    • Problem
    • Solution
    • Other description if necessary

Notes

Each worker subscribes to an AWS SQS queue. We don't need to handle any logic related to pulling or acknowledging message. AWS Lambda handles it automatically. The Lambda code simply processes the input message. The message will be considered success if there is no error thrown. The main handler is located in the Handler class. We also included some base classes for your reference.

Assume that these interfaces and classes have been already implemented in another Nuget package

  • SalesforceOAuthServiceClient
  • IOAuthTokenManager
  • IContactsServiceClient
  • IRemoteDataServiceClient
  • IOAuthTokenV2ServiceClient
  • ISyncSettingV2ServiceClient
  • ILogTrace

This is not fully working code! If there is anything you need clarification, feel free to ask.

ar.secondround's People

Contributors

nmtri1987 avatar

Watchers

James Cloos avatar  avatar

ar.secondround's Issues

LambdaServiceWithAppStore

  • Constructor:
    protected LambdaServiceWithAppStore() => Init(LoadConfigFromEnvVar);
    -> Suggestion: protected LambdaServiceWithAppStore() : base(LoadConfigFromEnvVar);
  • Why do we need to InitAppStore via Activator.CreateInstance -> always creates a new instance (TAppStore : SingletonAppStore)
    -> Suggestion: We can get instance of AppStore by calling SingletonAppStore.Instance or SingletonStore<typeof(TAppStore)>

SQSLambdaMessageHandler

  • IList ParseMessages(SQSEvent sqsEvent)
    return sqsEvent.Records.Select(
    record =>
    {
    // parse the json string to TMessage
    var message = JsonConvert.DeserializeObject(record.Body);

                  // validate message schema
                  message.Validate();
    
                  return message;
              }
          ).ToList();
    

-> Suggestion: Should wrap in try/catch block to log the error during parsing and validating message -> return default message if needed

TopicsSyncer/Handler

  • UpdateGroupNames

    • foreach (var task in groupTasks)
      {
      await task;
      }
    • foreach (var task in remoteTasks)
      {
      await task;
      }
      -> Suggestion: Consider to use await Task.WhenAll() to run async tasks
  • All the calls to svcSalesforce(GetAllPractifiCampaignsAsync, GetAllSalesforceCampaignsAsync...) should be replaced with Proxies, adapter

LambdaMessageHandler

  • Inherit LambdaServiceWithAppStore
  • Implement IMessageHandler
  • protected IServiceBusClient SvcServiceBus => SingletonStore.Get(()...
  • protected ISlackServiceClient SvcSlack = new SlackServiceClient(SlackServiceClientConfig.LoadConfigFromEnvVar());
    -> Suggestion: Should inject in constructor to make this class testable
  • public async Task HandleAsync(object reqData, ILambdaContext context)
    -> Suggestion:
    • Should inject ILogTrace in constructor, avoid creating instance of MessageHandlerLogTrace here
    • Keep one try/catch/finally block, remove another one
  • AlertErrorToSlack -> Task.WaitAll(SvcSlack.SendWithErrorHandler(slackMsg, logTrace));
    -> Suggestion: Task.Run(() => SvcSlack.SendWithErrorHandler(slackMsg, logTrace)). Just fire and forget, create new task from Thread pool to avoid deadlock, no need to get result

MessageHandler

  • public abstract class MessageHandler<TMessage, TAppStore> : IMessageHandler<TMessage> where TMessage : IMessage

-> Why do we need AppStore here ?
-> Suggestion:
public abstract class MessageHandler<TMessage> : IMessageHandler<TMessage> where TMessage : IMessage

  • public abstract Task<IEnumerable> ProcessAsync(TMessage message, ILogTrace logTrace);
    -> Suggestion: Should inject ILogTrace in Constructor

Coding standard, patterns

  • Should create a proxy classes (SalesForceContactProxy, SalesForceTopicProxy) to wrap and make some methods testable -> move logic of svcSalesforce, SalesforceUtil -> SalesForceContactProxy/SalesForceTopicProxy:
    public interface ISalesForceContactProxy
    {
    // Contacts
    GetAllContactsAsync
    GetNextPageAsync
    }
    public interface ISalesForceTopicProxy
    {
    // Topics
    GetAllSalesforceObjectsAsync...
    GetAllCampaignInteractionsAsync...
    GetAllCampaignsAsync...
    GetAllTopicsAsync...
    }
    -> Implementation:
    public class SalesForceContactProxy: ISalesForceContactProxy, IDisposable
    {
    ILogTrace _logger;
    AppStore _store;
    IConfig _config;

    ISalesforceServiceClientV2 _salesforceServiceClient;

    SalesForceContactProxy(ILogTrace logTrace, IConfig config)
    {
    _salesforceServiceClient = SalesforceServiceClientV2Factory.Create(...)
    }
    .... // Implement inteface

    protected virtual void Dispose(bool disposing) { _salesforceServiceClient.Dispose....}
    }

  • We should consider to create SaleforceTopicServiceAdapter to map object and SalesforceTopicMapping
    public class SalesForceServiceAdapter
    {
    ISalesForceProxy _proxy;
    public SalesForceServiceAdapter(ISalesForceTopicProxy proxy) { _proxy = proxy; }

    protected async Task<IList> GetAllSalesforceCampaignsAsync()
    ....
    }

ContactsSyncer/Handler

  • This class should:
    • Inherit from LambdaServiceWithAppStore
    • Implement IMessageHandler
  • ProcessAsync:
    • Remove do/while -> Replace by while loop -> move logic of GetContacts out of do/while, move logic of GetContactsNextPage to while loop to avoid checking string.IsNullOrWhiteSpace(getContactsData.NextRecordsUrl) twice
  • GetContacts
    • Should have try/catch block to catch error when making the call to other methods
    • Consider to lazy initialize getContactsFallbackLevel1Task, getContactsFallbackLevel2Task since if we have the data of the call to GetContactsWithOutOfSyncHandler, we don't need to call getContactsFallbackLevel1Task, getContactsFallbackLevel2Task
  • Consider when throwing exception inside GetContactsNextPage and GetContacts since it will stop the flow -> Just need to log the failed contacts and continue to fetch contacts to the end of page
  • static readonly object _lock = new object();
    -> Remove unused variable

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.