Skip to content

Commit

Permalink
Streaming (#22)
Browse files Browse the repository at this point in the history
* update schema in daemon ts files

* add stub for streaming endpoint

* add failing streaming test!

* use empty json array

* fix test and make it pass!!!!

* trunk fixes

* 🔄 "improve readme
"
Update anysphere/asphr commit SHA
🔗 anysphere/asphr@ef7929a

* make it easier to run two things at once

* save last_mono_index

* use empty array not null

* fix tests

* 🔄 "Merge branch 'main' into arvid/streaming
"
Update anysphere/asphr commit SHA
🔗 anysphere/asphr@256f3df

* small qol improvements

* 🔄 "small qol improvements
"
Update anysphere/asphr commit SHA
🔗 anysphere/asphr@f178ab6

* update gui proto

* sort based on timestamp

* fix race condition on independent things by removing forced coupling

* 🔄 "fix race condition on independent things by removing forced coupling
"
Update anysphere/asphr commit SHA
🔗 anysphere/asphr@0503176

* get each message exactly once

* not working!

* 🔄 "not working!
"
Update anysphere/asphr commit SHA
🔗 anysphere/asphr@69957a8

* update gui proto

* make new messages also streamed

* update tests for new filtering mechanism

* fix problems'

* only update when actuallynecessary

* add wrap3 because useful

* make sent and outbox work

* comply with iso c++

* trunk fmt

* clarifying comment

* clarify sorting order

* typescript super linter use prettier

* fix shellcheck i love shellcheck

* linting things

* add a generated comment on top

* add language to make linter happy

* trunk fmt all

* document scripts

* linter
  • Loading branch information
arvid220u authored Apr 3, 2022
1 parent 5ab5926 commit f5a9eaa
Show file tree
Hide file tree
Showing 34 changed files with 802 additions and 693 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,7 @@ jobs:
env:
VALIDATE_ALL_CODEBASE: false
JAVASCRIPT_DEFAULT_STYLE: prettier
TYPESCRIPT_DEFAULT_STYLE: prettier
IGNORE_GENERATED_FILES: true
DEFAULT_BRANCH: main
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 changes: 8 additions & 9 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ name: Mark stale issues and pull requests

on:
schedule:
- cron: '42 3 * * *'
- cron: "42 3 * * *"

jobs:
stale:

runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write

steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Stale issue message'
stale-pr-message: 'Stale pull request message'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "Stale issue message"
stale-pr-message: "Stale pull request message"
stale-issue-label: "no-issue-activity"
stale-pr-label: "no-pr-activity"
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"search.exclude": {
".trunk": true
}
}
43 changes: 18 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@ This repository, along with [anysphere/asphr](https://github.com/anysphere/asphr

Clone anysphere/asphr and anysphere/client and put them in a directory side-by-side. Then, in the `client` directory, run:

```
```bash
bazel build //...
```

to build, and

```
```bash
bazel test //...
```

to test.

## Develop GUI.
## Develop GUI

Checkout [the GUI Readme](gui/README.md)!

## Package

```
```bash
npm run package-mac
```

Make sure you have Xcode installed.

To enable notarization, first run

```
```bash
security find-identity -p basic -v
```

to see the developer certificates (there should be Developer ID Application and Developer ID Installer). Make note of the ten character code at the end: this is the teamId. Then run

```
```bash
xcrun notarytool store-credentials --apple-id "[email protected]" --team-id "ABCD123456" --keychain ~/Library/Keychains/login.keychain-db
```

Expand All @@ -52,37 +52,30 @@ Let `.env` contain the environment variables specified by `helpers/scripts/packa

Build:

```
```bash
bazel build //...
```

Run normal daemon:
In one terminal, run normal daemon:

```
```bash
./bazel-bin/daemon/daemon
```

Run daemon 2:
Open a new terminal and run
In a new terminal, run a second daemon:

```
export XDG_CONFIG_HOME=$HOME/.anysphere2/data
export XDG_RUNTIME_DIR=$HOME/.anysphere2/run
rm -rf ~/.anysphere2 && mkdir ~/.anysphere2 && ./bazel-bin/daemon/daemon -d "$HOME/.anysphere2/anysphere.sock" -c "$HOME/.anysphere2/config.json"
```bash
./wrap2.sh ./bazel-bin/daemon/daemon
```

Next, in a third terminal, run
To connect to daemon 1, run:

```
./bazel-bin/cli/asphr
```bash
./bazel-bin/cli/asphr [command]
```

to connect to daemon 1, and in a fourth terminal, run
To connect to daemon 2, run:

```bash
./wrap2.sh ./bazel-bin/cli/asphr [command]
```
export XDG_CONFIG_HOME=$HOME/.anysphere2/data
export XDG_RUNTIME_DIR=$HOME/.anysphere2/run
./bazel-bin/cli/asphr [command]
```

to connect to daemon 2.
56 changes: 30 additions & 26 deletions cli/as_cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ int main(int argc, char** argv) {

static Friend::FriendMap kFriends_map_;

auto *const binary_name = argv[0];

auto help = StrCat("Usage: \n",
// register
binary_name, " register: {name}\n",
// init-friend
binary_name, " init-friend: {name}\n",
// TODO(unknown): add-friend must have an init-friend before
binary_name, " add-friend: {name} {key}\n",
// TODO(unknown): explain the options better.
binary_name, " (s | m | send | msg | message) {name}\n",
binary_name, " (get-friends | friends)\n",
// TODO(unknown): explain that -a is optional.
binary_name, " (inbox | i) [-a | -all]\n", binary_name,
" socket {address}\n", binary_name, " kill\n", binary_name,
" status\n");
auto* const binary_name = argv[0];

auto help = StrCat(
"Usage: \n",
// register
binary_name, " register: {name}\n",
// init-friend
binary_name, " init-friend: {name}\n",
// TODO(unknown): add-friend must have an init-friend before
binary_name, " add-friend: {name} {key}\n",
// TODO(unknown): explain the options better.
binary_name, " (s | m | send | msg | message) {name}\n", binary_name,
" (get-friends | friends)\n",
// TODO(unknown): explain that -a is optional.
binary_name, " (inbox | i) [-a | -all]\n", binary_name,
" socket {address}\n", binary_name, " kill\n", binary_name, " status\n");

CommandLine cmd_line{argc, argv, help};

Expand All @@ -44,7 +44,7 @@ int main(int argc, char** argv) {
cout << "Anysphere CLI." << endl << endl;
cout << help << endl;
return 0;
};
}

auto command = command_status.value();

Expand Down Expand Up @@ -197,10 +197,13 @@ int main(int argc, char** argv) {
if (!status.ok()) {
cout << "get status failed: " << status.error_message() << endl;
return 0;
} cout << "Registered: " << (response.registered() ? "true" : "false")
<< endl;
cout << "Release commit hash: " << response.release_hash() << endl;

}

cout << "Registered: " << (response.registered() ? "true" : "false")
<< endl;
cout << "Release commit hash: " << response.release_hash() << endl;
cout << "Latency: " << response.latency_seconds() << endl;

} else if (command == "kill") {
grpc::ClientContext context;
asphrdaemon::KillRequest request;
Expand All @@ -211,8 +214,9 @@ int main(int argc, char** argv) {
if (!status.ok()) {
cout << "kill failed: " << status.error_message() << endl;
return 0;
} cout << "Successfully killed the daemon!" << endl;

}
cout << "Successfully killed the daemon!" << endl;

} else if (command == "change-latency" || command == "cltcy") {
auto latency_seconds = cmd_line.getArgument(2);
if (!latency_seconds.ok()) {
Expand All @@ -238,9 +242,9 @@ int main(int argc, char** argv) {
if (!status.ok()) {
cout << "change latency failed: " << status.error_message() << endl;
return 0;
} cout << "Successfully changed latency to " << latency << " seconds!"
<< endl;

}
cout << "Successfully changed latency to " << latency << " seconds!"
<< endl;

} else {
cout << "Unknown command: " << command << endl;
Expand Down
8 changes: 4 additions & 4 deletions cli/friend_struct.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ auto Friend::generate_key(unique_ptr<asphrdaemon::Daemon::Stub>& stub)
if (!status.ok()) {
cout << "generate friend key failed: " << status.error_message() << endl;
return absl::UnknownError("generate friend key failed");
} return response.key();

}
return response.key();
}

auto Friend::add(unique_ptr<asphrdaemon::Daemon::Stub>& stub, const string& key)
Expand All @@ -38,8 +38,8 @@ auto Friend::add(unique_ptr<asphrdaemon::Daemon::Stub>& stub, const string& key)
if (!status.ok()) {
cout << "add friend failed: " << status.error_message() << endl;
return absl::UnknownError("add friend failed");
} return absl::OkStatus();

}
return absl::OkStatus();
}

bool Friend::complete() const { return !name_is_empty(); }
9 changes: 5 additions & 4 deletions cli/inbox.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ void Inbox::update(unique_ptr<asphrdaemon::Daemon::Stub>& stub,
vector<pair<absl::Time, Message>> new_messages;

grpc::ClientContext context;
asphrdaemon::GetAllMessagesRequest request;
asphrdaemon::GetAllMessagesResponse response;
asphrdaemon::GetMessagesRequest request;
request.set_filter(asphrdaemon::GetMessagesRequest::ALL);
asphrdaemon::GetMessagesResponse response;

grpc::Status status = stub->GetAllMessages(&context, request, &response);
grpc::Status status = stub->GetMessages(&context, request, &response);

if (!status.ok()) {
cout << "get all messages failed: " << status.error_message() << endl;
Expand All @@ -38,4 +39,4 @@ void Inbox::update(unique_ptr<asphrdaemon::Daemon::Stub>& stub,
}

update(new_messages);
}
}
8 changes: 4 additions & 4 deletions client_lib/client_lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ extern constexpr size_t GUARANTEED_SINGLE_MESSAGE_SIZE =
auto get_base_config_dir() noexcept(false) -> std::filesystem::path {
// on Linux and on systems where XDG_CONFIG_HOME is defined, use it.
std::filesystem::path anysphere_home;
auto *config_home_maybe = std::getenv("XDG_CONFIG_HOME");
auto* config_home_maybe = std::getenv("XDG_CONFIG_HOME");
if (config_home_maybe == nullptr) {
// if not defined, default to $HOME/.anysphere
auto *home = std::getenv("HOME");
auto* home = std::getenv("HOME");
if (home == nullptr) {
// don't know what to do now.... there is literally nothing we can do
// without knowing the HOME directory. crash.
Expand Down Expand Up @@ -84,7 +84,7 @@ auto get_gui_config_dir() noexcept(false) -> std::filesystem::path {
// cli and gui processes.
auto get_runtime_dir() noexcept(false) -> std::filesystem::path {
std::filesystem::path runtime_home;
auto *runtime_home_maybe = std::getenv("XDG_RUNTIME_DIR");
auto* runtime_home_maybe = std::getenv("XDG_RUNTIME_DIR");
if (runtime_home_maybe == nullptr) {
// if not defined, there is no standard directory to put this in.
// we therefore use the base config dir / run.
Expand Down Expand Up @@ -115,7 +115,7 @@ auto get_socket_path() noexcept(false) -> std::filesystem::path {
// this is only the default location.
auto get_default_data_dir() noexcept(false) -> std::filesystem::path {
std::filesystem::path data_home;
auto *data_home_maybe = std::getenv("XDG_DATA_HOME");
auto* data_home_maybe = std::getenv("XDG_DATA_HOME");
if (data_home_maybe == nullptr) {
// if not defined, we are using ~/.anysphere to store all data.
// we therefore use the base config dir / run.
Expand Down
40 changes: 30 additions & 10 deletions daemon/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ auto Config::server_address() -> std::string {
Config::Config(const string& config_file_address)
: Config(read_json_file(config_file_address), config_file_address) {}

Config::Config(const asphr::json& config_json_input,
string config_file_address)
Config::Config(const asphr::json& config_json_input, string config_file_address)
: saved_file_address(std::move(config_file_address)),
db_rows_(CLIENT_DB_ROWS),
dummyMe("dummyMe", 0, "add_key", "", "", 0, false, 0, 0, 0, true),
Expand Down Expand Up @@ -252,8 +251,7 @@ auto Config::remove_friend(const string& name) -> absl::Status {
check_rep();

if (!friendTable.contains(name)) {
return {absl::StatusCode::kInvalidArgument,
"friend does not exist"};
return {absl::StatusCode::kInvalidArgument, "friend does not exist"};
}
friendTable.erase(name);

Expand Down Expand Up @@ -290,13 +288,29 @@ auto Config::get_friend(const string& name) const -> absl::StatusOr<Friend> {
return friendTable.at(name);
}

auto Config::update_friend(const Friend& f) -> void {
auto Config::update_friend(const string& name, const FriendUpdate& fs) -> void {
const std::lock_guard<std::mutex> l(config_mtx);

check_rep();

assert(friendTable.contains(f.name));
friendTable.insert_or_assign(f.name, f);
assert(friendTable.contains(name));

auto old_friend = friendTable.at(name);

auto new_friend =
Friend(name, fs.read_index.value_or(old_friend.read_index),
fs.add_key.value_or(old_friend.add_key),
fs.read_key.value_or(old_friend.read_key),
fs.write_key.value_or(old_friend.write_key),
fs.ack_index.value_or(old_friend.ack_index),
fs.enabled.value_or(old_friend.enabled),
fs.latest_ack_id.value_or(old_friend.latest_ack_id),
fs.latest_send_id.value_or(old_friend.latest_send_id),
fs.last_receive_id.value_or(old_friend.last_receive_id),
fs.dummy.value_or(old_friend.dummy));

friendTable.insert_or_assign(name, new_friend);

save();

check_rep();
Expand Down Expand Up @@ -369,7 +383,7 @@ auto Config::wait_until_killed_or_seconds(int seconds) -> bool {
// private method; hence no check_rep, no lock
auto Config::check_rep() const -> void {
assert(!saved_file_address.empty());
assert(data_dir != "");
ASPHR_ASSERT_NEQ(data_dir, "");
assert(db_rows_ > 0);

assert(latency_ >= 1);
Expand Down Expand Up @@ -402,6 +416,9 @@ auto Config::check_rep() const -> void {

// private method; hence, no check_rep, no lock
auto Config::save() -> void {
// only save if rep is ok!
check_rep();

asphr::json config_json;
config_json["has_registered"] = has_registered_;
config_json["data_dir"] = data_dir;
Expand Down Expand Up @@ -434,5 +451,8 @@ auto Config::initialize_dummy_me() -> void {
dummyMe = Friend("dummyMe", 0, "add_key", dummy_read_write_keys.first,
dummy_read_write_keys.second, 0, false, 0, 0, 0, true);

save();
}
// don't save at the end because initialize_dummy_me is called before other
// things are initialized, so if we saved here we would save an invalid
// config. that's why we also don't have a check-rep here: check-rep is not
// guaranteed to pass!
}
Loading

0 comments on commit f5a9eaa

Please sign in to comment.