diff options
Diffstat (limited to 'software')
-rw-r--r-- | software/bash.page | 2 | ||||
-rw-r--r-- | software/postgres.page | 17 | ||||
-rw-r--r-- | software/python.page | 21 | ||||
-rw-r--r-- | software/rsyslog.page | 20 | ||||
-rw-r--r-- | software/rust.page | 117 |
5 files changed, 174 insertions, 3 deletions
diff --git a/software/bash.page b/software/bash.page index 0d5325b..5d82fdc 100644 --- a/software/bash.page +++ b/software/bash.page @@ -37,6 +37,8 @@ Note that `join`, `grep`, and others sometimes exit non-zero return codes on purpose (eg, pipe input closed or found no matches, as expected), which makes life difficult. Sometimes `|| true` is enough to get around this. +More on this: <http://redsymbol.net/articles/unofficial-bash-strict-mode/> + ## General Style Google has a style guide: https://google.github.io/styleguide/shell.xml diff --git a/software/postgres.page b/software/postgres.page index bdb01d8..7d05074 100644 --- a/software/postgres.page +++ b/software/postgres.page @@ -15,3 +15,20 @@ Basic status from the psql command line: \l+ (list databases) \dt+ (describe table) + +## Temporary Databases in Tests + +Try `pg_tmp`, though it may not work with high concurrency (due to internal +postgres locking), and might need special configuration in CI environments. + +Debian also ships with `pg_virtualenv` for temporary databases. + +--------- + +More refs/links: + +- https://stackoverflow.com/questions/9604723/alternate-output-format-for-psql +- https://brandur.org/postgres-connections +- https://www.citusdata.com/blog/2017/07/16/customizing-my-postgres-shell-using-psqlrc/ +- `bind "^R" em-inc-search-prev` + diff --git a/software/python.page b/software/python.page index 0fd2531..0fc3c8d 100644 --- a/software/python.page +++ b/software/python.page @@ -205,3 +205,24 @@ and create a `pytest.ini` like: norecursedirs = .svn _build tmp* Need to mock? <https://blog.fugue.co/2016-02-11-python-mocking-101.html> + +Debugging Memory Usage +------------------------ + +Most helpful tools I found were `psutil` and `pympler` (both need to be +installed). + + import os, psutil + process = psutil.Process(os.getpid()) + print(process.memory_info().rss) + # ... do some stuff ... + print(process.memory_info().rss) + +and + + from pympler import tracker + tr = tracker.SummaryTracker() + tr.print_diff() + + # ... do some stuff ... + tr.print_diff() diff --git a/software/rsyslog.page b/software/rsyslog.page new file mode 100644 index 0000000..b55c127 --- /dev/null +++ b/software/rsyslog.page @@ -0,0 +1,20 @@ + +Put these in files like `/etc/rsyslog.d/40-grobid-skip.conf`. + +Filter out lines from a given program: + + :programname, isequal, "GROBID" ~ + +Or matching a pattern: + + :msg, startswith, "inserting line to HBase: sha1:" + :msg, contains, " INFO GET http" + +For list of operations ("isequal", "regex", "contains"): + + https://www.rsyslog.com/doc/v8-stable/configuration/filters.html + +For list of properties (":msg", ":programname"): + + https://www.rsyslog.com/doc/v8-stable/configuration/properties.html + diff --git a/software/rust.page b/software/rust.page index df99de4..dc900c8 100644 --- a/software/rust.page +++ b/software/rust.page @@ -3,9 +3,10 @@ Rust ## Resources -- [http://xion.io/post/code/rust-iter-patterns.html]() -- [https://deterministic.space/rust-cli-tips.html]() -- [https://manishearth.github.io/blog/2018/01/10/whats-tokio-and-async-io-all-about/]() +- <http://xion.io/post/code/rust-iter-patterns.html> +- <https://deterministic.space/rust-cli-tips.htm> +- <https://manishearth.github.io/blog/2018/01/10/whats-tokio-and-async-io-all-about/> +- <https://saghm.github.io/five-rust-things/> Optimization: use `RUSTFLAGS="-C target-cpu=native"` to take advantage of CPU special features. @@ -22,3 +23,113 @@ Run tests with stdout output: To run tests with logging enabled (eg, with `env_logger`), make sure you add `env_logger::init()` to the test function itself. + + +## map() and Result Ergonomics + +`.collect()` has some magical features! In addition to turning an iterator of +`Item` into `Vec<Item>`, it will turn an iterator of `Result<Item>` into +`Result<Vec<Item>>`. This makes it really useful for the end of functions. + +This is particularly useful for resolving some categories of "error handling in +map closures": you can use `?` in the map closure as long as you wrap the happy +path with `Ok()` and call collect on the outside. Eg: + + let list: Vec<Item> = junk + .iter() + .map(|thing| Ok(Item { + a: thing.a, + b: fixup(thing.widget)?, + })) + .collect::Result<Vec<Item>>()?; + +What about when `map` over an `Option`? Eg: + + let toy = Shiny { + a: 123, + b: component.map(|v| paint(v).expect("paint to succeed"), + }; + +Should use match in this case: + + let toy = Shiny { + a: 123, + b: match component { + None => None, + Some(v) => Some(paint(v)?), + }, + }; + +## 2020-05-17 Reading + +While working on fatcat-cli tool, checked the The Rust Programming Language +book to read about trait objects and the `dyn` keyword, which I had ignored +previously. + +They seem like they could be used in a few places in fatcat-server rust code. +We don't particularly care about per-function-call performance there, and most +entities are already allocated on the heap. + +Other small syntax and thing learned: + +Can copy a struct while only updating specific fields with ".." syntax. Might +use this in fatcat-cli for update mutation. + +This is the cleanest example of using ErrorKind that I have seen: + + let f = match f { + Ok(file) => file, + Err(error) => match error.kind() { + ErrorKind::NotFound => match File::create("hello.txt") { + Ok(fc) => fc, + Err(e) => panic!("Problem creating the file: {:?}", e), + }, + other_error => { + panic!("Problem opening the file: {:?}", other_error) + } + }, + }; + +I didn't realize that test code may get compiled into non-test binaries unless +annotated with `#[cfg(test)]`. You are supposed to create a sub-module within +each `src/` file with unittests, like: + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } + } +This doesn't apply to `tests/` directory, which is for integration tests. + +The common pattern for binary crates (vs. library crates) is to have `main.rs` +and `lib.rs`, with any code that needs to be tested in `lib.rs` (aka, all the +actual logic). + +I think I knew `eprintln!()` (for stderr) vs. `println!()` (for stdout), but +good to remember. + +There is a description of how to avoid memory leaks with reference counting +using "weak" `Rc` references. Probably worth reading the [entire chapter on smart pointers](https://doc.rust-lang.org/book/ch15-06-reference-cycles.html#preventing-reference-cycles-turning-an-rct-into-a-weakt) +(including Box, Rc, RefCell) again. + +For the `Sized` trait, and `Sized` trait alone, can specify an ambiguous trait +constraint with `?` to indicate "may or may not be Sized", which doesn't really +mean anything but does explicitly allow generic functions over non-sized traits +like: + + fn my_generic_func<T: ?Sized>(t: &T) { + // --snip-- + } + +A trait can depend on another trait. For example, a PrettyPrint trait could +rely on Display (and impl functions could call functions from Display). This is +done on the trait definition line. Such a trait is called a "supertrait". + +Implementing Deref on a wrapper type allows transparent access to all the trait +methods on the interior object. + +Also, a new longer post on error handling: <https://nick.groenen.me/posts/rust-error-handling/> |