Skip to content

Commit

Permalink
ios & backend challenges update (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
aymericbeaumet authored Nov 19, 2023
1 parent d5e2314 commit c4164de
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 31 deletions.
12 changes: 10 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ on:
- "**.md"

env:
GO_VERSION: "1.21.3" # https://go.dev/dl/
GOLANGCI_LINT_VERSION: "v1.55.1" # https://github.com/golangci/golangci-lint/releases
GO_VERSION: "1.21.4" # https://go.dev/dl/
GOLANGCI_LINT_VERSION: "v1.55.2" # https://github.com/golangci/golangci-lint/releases

jobs:
lint:
Expand All @@ -29,6 +29,14 @@ jobs:
skip-cache: true
working-directory: ./ios/server

security:
runs-on: ubuntu-latest
steps:
- uses: golang/govulncheck-action@v1
with:
go-version-input: ${{ env.GO_VERSION }}
work-dir: ./ios/server

build:
runs-on: ubuntu-latest
steps:
Expand Down
62 changes: 62 additions & 0 deletions backend/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Backend Challenge

This challenge is part of the backend hiring process at [Heart
Hands](https://hearthands.tech/).

## Why this challenge?

Heart Hands is operating with a small team of dedicated & talented people. We
are looking for seasoned engineers with a deep technical knowledge, strong
understanding of their technical stack, and excellent product intuitions to join
our team.

This exercise has been designed to give a glimpse of what it is like to build a
messaging app, and the kind of technical challenges we face and care about. We
are expecting you to spend between 4 and 6 hours on this challenge.

## Instructions

You are tasked with the server-side implementation of a messaging app that
allows clients to send and receive text messages in private 1:1 chats.

We enforce no technical constraints: you are free to choose the language, data
layer, network protocol, and design your API as you see fit. You are
purposefully being given a lot of freedom here, and you will not be judged on
these decisions alone, but we will challenge the understanding of the trade-offs
you make.

Functional requirements:

- [ ] Clients should be able to uniquely identify themselves with a phone number
(without authentication)
- [ ] Clients should be able to send messages to other clients via their phone
numbers
- [ ] Clients should be able to list their chats
- [ ] Clients should be able to list all messages in a chat

## Bonus

Some topics that we find interesting to dig:

- [ ] Choose a network protocol that enables soft real-time message delivery to the clients
- [ ] Make the server message ingestion idempotent
- [ ] Add support for sent/delivered/read message status
- [ ] Add support for chats and messages pagination
- [ ] Implement SMS phone number verification to authenticate the clients
- [ ] Support SMS forwarding to relay the messages to the clients phone numbers

## Challenge Review

We know you only have a limited time alloted to deliver this challenge, and thus
will have to prioritize what you work on. A few things that are important for us
and that will be considered during the review:
- **documentation**: is the readme clear? are important parts of the code
documented?
- **impact**: which features did you prioritize?
- **maintainability**: is the code well-structured and easy to read/evolve?
- **robustness**: is the code tested or easily testable? are edge-cases
considered? is static analysis leveraged?

***

Good luck, and enjoy!
50 changes: 32 additions & 18 deletions ios/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,41 @@ Hands](https://hearthands.tech/).

## Why this challenge?

Heart Hands is operating with a small team of dedicated and talented people. We
Heart Hands is operating with a small team of dedicated & talented people. We
are looking for seasoned engineers with a deep technical knowledge, strong
understanding of their technical stack, and good product intuitions to join our
team.
understanding of their technical stack, and excellent product intuitions to join
our team.

This challenge has been designed to give a glimpse of what it is like to build a
This exercise has been designed to give a glimpse of what it is like to build a
messaging app, and the kind of technical challenges we face and care about. We
are expecting you to spend no more than 48 hours on this.
are expecting you to spend between 4 and 6 hours on this challenge.

## Summary
## Instructions

You are tasked to develop a messaging app that allows to send and receive
messages with several bots, each in their own chat.
You are tasked with the implementation of an iOS messaging app that allows to
communicate (send and receive text messages) with bots, each in their own 1:1
chat.

A server is available for you to use, you can read more about it in
[`./server`](./server). The documentation contains informations on how it can be
run and what kinds of API endpoints are available.
A server is available for you to use. You can read more about it in
[`./server`](./server). Its documentation contains informations on how it can be
run, and what kinds of API endpoints & entities are available.

## Requirements

What are we expecting you to build?
Functional requirements:

- [ ] The app should start on a screen showing the list of all chats
- [ ] The app should allow opening each chat individually
- [ ] The app should allow sending messages to a chat
- [ ] The app should reflect the messages sent to and received from the server
- [ ] The app should be resilient to bad network conditions (drops & timeouts)

## Bonus

What could be implemented to improve the UX?
Some topics that we find interesting to dig:

- [ ] Make the app work offline (both for app state and sending)
- [ ] Make the app resilient to bad network conditions (retries & timeouts)
- [ ] Make the app idempotent in regards to what you send and receive
- [ ] Integrate a splashscreen to hide chats while the app is loading
- [ ] Add support for optimisic sending to give instantaneity in the UI
- [ ] Add support for optimistic sending to give instantaneity in the UI
- [ ] Add support for a local read/unread indicator
- [ ] Avoid block changing states so the app feels fluid & snappy
- [ ] Make the app compatible to run on iPad and macOS
Expand All @@ -49,8 +48,23 @@ What could be implemented to improve the UX?

## Design

We have prepared a design to help you during this challenge.
We have prepared a design to help you during this challenge. You will also
receive the Figma link along with the challenge instructions.

![design](./design.png)

## Challenge Review

We know you only have a limited time alloted to deliver this challenge, and thus
will have to prioritize what you work on. A few things that are important for us
and that will be considered during the review:
- **documentation**: is the readme clear? are important parts of the code
documented?
- **impact**: which features did you prioritize?
- **maintainability**: is the code well-structured and easy to read/evolve?
- **robustness**: is the code tested or easily testable? are edge-cases
considered? is static analysis leveraged?

***

Good luck, and enjoy!
6 changes: 3 additions & 3 deletions ios/server/go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module github.com/hearthands/challenges/ios/server

go 1.21.3
go 1.21.4

require (
github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/render v1.0.3
github.com/r3labs/sse/v2 v2.10.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
)

require (
github.com/ajg/form v1.5.1 // indirect
golang.org/x/net v0.0.0-20191116160921-f9c825593386 // indirect
golang.org/x/net v0.18.0 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
)
4 changes: 4 additions & 0 deletions ios/server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/net v0.0.0-20191116160921-f9c825593386 h1:ktbWvQrW08Txdxno1PiDpSxPXG6ndGsfnJjRRtkM0LQ=
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
Expand Down
6 changes: 3 additions & 3 deletions ios/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import (
)

var (
hostname = envOrDefault("HOSTNAME", "localhost") // hostname used by the server
port = envOrDefault("PORT", "3000") // port used by the server
limit = 100 // maximum number of entities returned in a single request
hostname = envOrDefault("HTTP_HOST", "localhost") // hostname used by the server
port = envOrDefault("PORT", "3000") // port used by the server
limit = 100 // maximum number of entities returned in a single request
)

//go:embed data.json
Expand Down
21 changes: 17 additions & 4 deletions ios/server/readme.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
# iOS Challenge - Server Companion

This server is used as a companion for the iOS challenge. Persistence is
in-memory, restarting the server will reset its state.
in-memory, and restarting the server will reset its state.

The server will sometime be a bit capricious, you might observe:
- failure to receive a response
- server timing out when trying to send a message
- timeouts when trying to send a message
- duplicate events being received in the messages stream

When that happens, you should retry and react accordingly.

## How to start the server?

1. You need to install Go on your system: follow the [official documentation](https://go.dev/doc/install)
2. Then execute the command: `go run .`
2. Then, execute the command: `go run .`

## How to make the server reachable from another machine?

You might want to allow the server to be reached from another machine
(simulator or a phone for example). One way to do that is to use [ngrok]().

1. You need to install Ngrok on your system: follow the [official
documentation](https://ngrok.com/download)
2. Then, after having started the server (see above), execute the command: `ngrok http 3000`

This will give you a public URL of the form
`https://9f98-62-194-145-77.ngrok.io`, that can be used to reach your server
from any system that has an internet connection.

## API Documentation

This API exposes a few HTTP endpoints, and an SSE stream. It allows to list
This API exposes a few HTTP endpoints and an SSE stream. It allows to list
chats, and read & write messages.

### Notes
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Challenges [![ci status](https://github.com/hearthandsinc/challenges/actions/workflows/ci.yml/badge.svg)](https://github.com/hearthandsinc/challenges/actions/workflows/ci.yml)

This repository contains the [Heart Hands](https://hearthands.tech/) engineering
challenges for [iOS](./ios) and _backend (soon)_.
challenges for [iOS](./ios) and [backend](./backend) positions.

## Feedbacks

Expand Down

0 comments on commit c4164de

Please sign in to comment.